knitr::opts_chunk$set(cache=FALSE, message=FALSE, warning=FALSE, prompt=FALSE,      tidy=TRUE, comment=NA)

Introdução

No serviço público é comum que alguns servidores não aposentam na data em que começa a ter o direito a aposentadoria e permanecem no trabalho até o tempo da idade compulsória recebendo um abono. Dessa forma, o objetivo do estudo consiste na exploração da teoria de análise de regressão logística para delinear o perfil dos servidores que adquirem o direito ao abono salarial e decidem se continuam trabalhando = 0 ou não = 1, situação que será a variável resposta de interesse neste caso.

Base de Dados

Para subsidiar este estudo, foram coletadas informações do Data Warehouse do Sistema Integrado de Administração de Pessoal - DW SIAPE dos servidores públicos do Ministério da Economia - ME, ativos e inativos no período de janeiro de 2019 a julho de 2019.

As informações extraídas foram:

• Nome • Sexo • CPF (chave primária) • Matricula SIAPE • CLASSE_CARGO • PADRAO_CARGO • SITUACAO_VINCULO • REGIME_JURIDICO • JORNADA_DE_TRABALHO • Remuneração • Ano/Mês inicial do abono de permanência • Valor Abono (caso tenha) • Todas as gratificações e funções comissionadas • Funções – VPNI • Quantidade de dependentes • Descrição do cargo emprego • Nível de Escolaridade • Denominação do órgão de atuação • UF da UPAG de vinculação • Denominação unidade organizacional • ORGSUP_EXERCICIO • UF da Residência • Cidade da residência • Situação servidor • Tipo DE Aposentadoria • Data ingresso no serviço público • Data de nascimento • DATA ocorrência inatividade

Descritivas dos dados

Inicialmente, selecionou-se o último mês desta base de dados, junho de 2019, e buscou os tempos iniciais para o estudo, ou seja, a data de início do abono e, para os casos da ocorrência do evento de aposentadorias, buscou-se a data deste fato.

mes0619 <- read.csv2("dados.csv")
mes0619 %>% DT::datatable()
summary(mes0619[, -c(1, 2)])
 SEXO                                          CARGO         JORNADA     
 F:9937   AUDITOR-FISCAL DA RECEITA FEDERAL BRASIL:5357   Min.   :20.00  
 M:8042   AGENTE ADMINISTRATIVO                   :3217   1st Qu.:40.00  
          ANALISTA TRIBUTARIO REC FEDERAL BRASIL  :2149   Median :40.00  
          AUDITOR FISCAL DO TRABALHO              :1335   Mean   :39.93  
          TECNICO DO SEGURO SOCIAL                :1167   3rd Qu.:40.00  
          AGENTE DE PORTARIA                      : 666   Max.   :40.00  
          (Other)                                 :4088                  
         Tipo_Regiao             id_ini_serv_pub  Idade_inicio_Serv
 Cidade_Grande :9122   entre 20 a 30 anos:10189   Min.   :11.88    
 Cidade_Média  :7364   entre 30 e 40 anos: 5214   1st Qu.:23.21    
 Cidade_Pequena:1493   mais de 40 anos   : 1378   Median :27.36    
                       menos de 20 anos  : 1198   Mean   :28.72    
                                                  3rd Qu.:32.98    
                                                  Max.   :62.03    
                                                                   
             id_aposentad  anos_de_aposent  Idade_Aposentadoria
 entre 50 a 60 anos:4704   Min.   : 0.093   Min.   :48.57      
 entre 60 e 70 anos:4328   1st Qu.: 1.619   1st Qu.:56.77      
 mais de 70 anos   : 472   Median : 4.636   Median :60.06      
 menos de 50 anos  :   5   Mean   : 4.901   Mean   :60.56      
 NA's              :8470   3rd Qu.: 7.463   3rd Qu.:63.92      
                           Max.   :15.126   Max.   :75.04      
                           NA's   :8470     NA's   :8470       
       D               R             liquido            desc_per      
 Min.   :    0   Min.   :  2895   Min.   :   302.4   Min.   :0.00000  
 1st Qu.: 1580   1st Qu.:  7917   1st Qu.:  6673.3   1st Qu.:0.07302  
 Median : 2676   Median : 20449   Median : 16356.8   Median :0.15176  
 Mean   : 3593   Mean   : 23833   Mean   : 20240.2   Mean   :0.17531  
 3rd Qu.: 4556   3rd Qu.: 42254   3rd Qu.: 34489.4   3rd Qu.:0.24943  
 Max.   :35071   Max.   :132037   Max.   :112528.6   Max.   :0.97570  
                                                                      
        Desc_Renda_Bruta     Qtde_dependentes     tempo         
 até 20%        :11157   até dois    : 6884   Min.   : 0.00274  
 entre 20% a 30%: 3743   dois ou mais:  543   1st Qu.: 2.02877  
 entre 30% a 40%: 2529   Nenhum      :10552   Median : 4.49589  
 mais de 40%    :  550                        Mean   : 5.40113  
                                              3rd Qu.: 7.83425  
                                              Max.   :20.61370  
                                                                
     status      
 Min.   :0.0000  
 1st Qu.:0.0000  
 Median :1.0000  
 Mean   :0.5289  
 3rd Qu.:1.0000  
 Max.   :1.0000  
                 

Exploração dos Dados de Sobrevivência - Estimador Kaplan-Meier

A partir do Estimador de Kaplan-Meier é possível observar o tempo mediano de 7.66 anos que os servidores em abono salarial permanecem no trabalho até decidirem aposentarem.

require("ggplot2")
.df <- na.omit(data.frame(x = mes0619$tempo, y = mes0619$status, z = factor("At risk")))
.df <- .df[do.call(order, .df[, c("z", "x"), drop = FALSE]), , drop = FALSE]
.fit <- survival::survfit(survival::Surv(time = x, event = y, type = "right") ~ 
    z, .df)
.fit <- data.frame(x = .fit$time, y = .fit$surv, nrisk = .fit$n.risk, nevent = .fit$n.event, 
    ncensor = .fit$n.censor, upper = .fit$upper, lower = .fit$lower)
.df <- .df[!duplicated(.df[, c("x", "z")]), ]
.df <- .fit <- data.frame(.fit, .df[, c("z"), drop = FALSE])
.med <- plyr::ddply(.fit, plyr::.(z), function(x) {
    data.frame(median = min(subset(x, y < (0.5 + .Machine$double.eps^0.5))$x))
})
.df <- .fit <- rbind(unique(data.frame(x = 0, y = 1, nrisk = NA, nevent = NA, 
    ncensor = NA, upper = 1, lower = 1, .df[, c("z"), drop = FALSE])), .fit)
.cens <- subset(.fit, ncensor == 1)
.tmp1 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) max(d$nrisk, 
    na.rm = TRUE))))
.tmp1$x <- 0
.nrisk <- .tmp1
for (i in 1:3) {
    .df <- subset(.fit, x < 7 * i)
    .tmp2 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) if (all(is.na(d$nrisk))) 
        NA else min(d$nrisk - d$nevent - d$ncensor, na.rm = TRUE))))
    .tmp2$x <- 7 * i
    .tmp2$Freq[is.na(.tmp2$Freq)] <- .tmp1$Freq[is.na(.tmp2$Freq)]
    .tmp1 <- .tmp2
    .nrisk <- rbind(.nrisk, .tmp2)
}
.nrisk$y <- rep(seq(0.025, 0.025, -0.05), 4)
.plot <- ggplot(data = .fit, aes(x = x, y = y, colour = z)) + geom_step(data = subset(.fit, 
    !is.na(upper)), aes(y = upper), size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, 
    na.rm = FALSE) + geom_step(data = subset(.fit, !is.na(lower)), aes(y = lower), 
    size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, na.rm = FALSE) + geom_step(size = 1.5) + 
    geom_linerange(data = .cens, aes(x = x, ymin = y, ymax = y + 0.02), size = 1.5) + 
    geom_vline(data = .med, aes(xintercept = median), colour = "black", lty = 2) + 
    scale_x_continuous(breaks = seq(0, 21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 
    1), expand = c(0.01, 0)) + scale_colour_brewer(palette = "Set1") + xlab("Tempo em anos de abono") + 
    ylab("Probabilidade S(t)") + labs(title = "Estimador de Kaplan-Meier") + 
    theme_grey(base_size = 14, base_family = "sans") + theme(legend.position = "none")
.nrisk$y <- 0.5
.plot2 <- ggplot(data = .nrisk, aes(x = x, y = y, label = Freq, colour = z)) + 
    geom_text(size = 14 * 0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 
    21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1)) + 
    scale_colour_brewer(palette = "Set1") + ylab("Tempo em anos de abono") + 
    RcmdrPlugin.KMggplot2::theme_natrisk(theme_grey, 14, "sans")
.plot3 <- ggplot(data = subset(.nrisk, x == 0), aes(x = x, y = y, label = z, 
    colour = z)) + geom_text(hjust = 0, size = 14 * 0.282, family = "sans") + 
    scale_x_continuous(limits = c(-5, 5)) + scale_y_continuous(limits = c(0, 
    1)) + scale_colour_brewer(palette = "Set1") + RcmdrPlugin.KMggplot2::theme_natrisk21(theme_grey, 
    14, "sans")
.plotb <- ggplot(.df, aes(x = x, y = y)) + geom_blank() + RcmdrPlugin.KMggplot2::theme_natriskbg(theme_grey, 
    14, "sans")
grid::grid.newpage()
grid::pushViewport(grid::viewport(layout = grid::grid.layout(2, 2, heights = unit(c(1, 
    2.5), c("null", "lines")), widths = unit(c(4, 1), c("lines", "null")))))
print(.plotb, vp = grid::viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))
print(.plot, vp = grid::viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(.plot2, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1:2))
print(.plot3, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1))

.plot <- recordPlot()
print(.plot)
rm(.df, .fit, .pmed, .med, .cens, .tmp1, .tmp2, .nrisk, .plot, .plot2, .plot3, 
    .plotb)
require("ggplot2")
.df <- na.omit(data.frame(x = mes0619$tempo, y = mes0619$status, z = mes0619$SEXO))
.df <- .df[do.call(order, .df[, c("z", "x"), drop = FALSE]), , drop = FALSE]
.fit <- survival::survfit(survival::Surv(time = x, event = y, type = "right") ~ 
    z, .df)
.pval <- plyr::ddply(.df, plyr::.(), function(x) {
    data.frame(x = 0, y = 0, df = 1, chisq = survival::survdiff(survival::Surv(time = x, 
        event = y, type = "right") ~ z, x)$chisq)
})
.pval$label <- paste0("paste(italic(p), \" = ", signif(1 - pchisq(.pval$chisq, 
    .pval$df), 3), "\")")
.fit <- data.frame(x = .fit$time, y = .fit$surv, nrisk = .fit$n.risk, nevent = .fit$n.event, 
    ncensor = .fit$n.censor, upper = .fit$upper, lower = .fit$lower)
.df <- .df[!duplicated(.df[, c("x", "z")]), ]
.df <- .fit <- data.frame(.fit, .df[, c("z"), drop = FALSE])
.df <- .fit <- rbind(unique(data.frame(x = 0, y = 1, nrisk = NA, nevent = NA, 
    ncensor = NA, upper = 1, lower = 1, .df[, c("z"), drop = FALSE])), .fit)
.cens <- subset(.fit, ncensor == 1)
.tmp1 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) max(d$nrisk, 
    na.rm = TRUE))))
.tmp1$x <- 0
.nrisk <- .tmp1
for (i in 1:3) {
    .df <- subset(.fit, x < 7 * i)
    .tmp2 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) if (all(is.na(d$nrisk))) 
        NA else min(d$nrisk - d$nevent - d$ncensor, na.rm = TRUE))))
    .tmp2$x <- 7 * i
    .tmp2$Freq[is.na(.tmp2$Freq)] <- .tmp1$Freq[is.na(.tmp2$Freq)]
    .tmp1 <- .tmp2
    .nrisk <- rbind(.nrisk, .tmp2)
}
.nrisk$y <- rep(seq(0.075, 0.025, -0.05), 4)
.plot <- ggplot(data = .fit, aes(x = x, y = y, colour = z)) + geom_step(data = subset(.fit, 
    !is.na(upper)), aes(y = upper), size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, 
    na.rm = FALSE) + geom_step(data = subset(.fit, !is.na(lower)), aes(y = lower), 
    size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, na.rm = FALSE) + geom_step(size = 1.5) + 
    geom_linerange(data = .cens, aes(x = x, ymin = y, ymax = y + 0.02), size = 1.5) + 
    geom_text(data = .pval, aes(y = y, x = x, label = label), colour = "black", 
        hjust = 0, vjust = -0.5, parse = TRUE, show.legend = FALSE, size = 14 * 
            0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 21, 
    by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1), expand = c(0.01, 
    0)) + scale_colour_brewer(palette = "Set1") + xlab("Tempo em anos de abono") + 
    ylab("Probabidade S(t)") + labs(colour = "SEXO") + labs(title = "Estimador de Kaplan-Meier") + 
    theme_grey(base_size = 14, base_family = "sans") + theme(legend.position = c(1, 
    1), legend.justification = c(1, 1), legend.background = element_rect(fill = "transparent"))
.nrisk$y <- ((.nrisk$y - 0.025)/(max(.nrisk$y) - 0.025) + 0.5) * 0.5
.plot2 <- ggplot(data = .nrisk, aes(x = x, y = y, label = Freq, colour = z)) + 
    geom_text(size = 14 * 0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 
    21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1)) + 
    scale_colour_brewer(palette = "Set1") + ylab("Probabidade S(t)") + RcmdrPlugin.KMggplot2::theme_natrisk(theme_grey, 
    14, "sans")
.plot3 <- ggplot(data = subset(.nrisk, x == 0), aes(x = x, y = y, label = z, 
    colour = z)) + geom_text(hjust = 0, size = 14 * 0.282, family = "sans") + 
    scale_x_continuous(limits = c(-5, 5)) + scale_y_continuous(limits = c(0, 
    1)) + scale_colour_brewer(palette = "Set1") + RcmdrPlugin.KMggplot2::theme_natrisk21(theme_grey, 
    14, "sans")
.plotb <- ggplot(.df, aes(x = x, y = y)) + geom_blank() + RcmdrPlugin.KMggplot2::theme_natriskbg(theme_grey, 
    14, "sans")
grid::grid.newpage()
grid::pushViewport(grid::viewport(layout = grid::grid.layout(2, 2, heights = unit(c(1, 
    3), c("null", "lines")), widths = unit(c(4, 1), c("lines", "null")))))
print(.plotb, vp = grid::viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))
print(.plot, vp = grid::viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(.plot2, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1:2))
print(.plot3, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1))

.plot <- recordPlot()
print(.plot)
rm(.df, .fit, .pval, .ppval, .cens, .tmp1, .tmp2, .nrisk, .plot, .plot2, .plot3, 
    .plotb)
.Survfit <- survfit(Surv(tempo, status, type = "right") ~ SEXO, conf.type = "log", 
    conf.int = 0.95, type = "kaplan-meier", error = "greenwood", data = mes0619)
.Survfit
Call: survfit(formula = Surv(tempo, status, type = "right") ~ SEXO, 
    data = mes0619, error = "greenwood", conf.type = "log", conf.int = 0.95, 
    type = "kaplan-meier")

          n events median 0.95LCL 0.95UCL
SEXO=F 9937   5256   7.66    7.42    7.95
SEXO=M 8042   4253   6.67    6.46    6.94
quantile(.Survfit, quantiles = c(0.25, 0.5, 0.75))
$quantile
             25       50       75
SEXO=F 3.463014 7.657534 14.91233
SEXO=M 2.906849 6.673973 11.42192

$lower
             25       50       75
SEXO=F 3.317808 7.419178 14.45479
SEXO=M 2.772603 6.460274 11.11507

$upper
             25       50       75
SEXO=F 3.621918 7.947945 15.20274
SEXO=M 3.021918 6.936986 11.68493
remove(.Survfit)
require("ggplot2")
.df <- na.omit(data.frame(x = mes0619$tempo, y = mes0619$status, z = mes0619$id_ini_serv_pub))
.df <- .df[do.call(order, .df[, c("z", "x"), drop = FALSE]), , drop = FALSE]
.fit <- survival::survfit(survival::Surv(time = x, event = y, type = "right") ~ 
    z, .df)
.pval <- plyr::ddply(.df, plyr::.(), function(x) {
    data.frame(x = 0, y = 0, df = 3, chisq = survival::survdiff(survival::Surv(time = x, 
        event = y, type = "right") ~ z, x)$chisq)
})
.pval$label <- paste0("paste(italic(p), \" = ", signif(1 - pchisq(.pval$chisq, 
    .pval$df), 3), "\")")
.fit <- data.frame(x = .fit$time, y = .fit$surv, nrisk = .fit$n.risk, nevent = .fit$n.event, 
    ncensor = .fit$n.censor, upper = .fit$upper, lower = .fit$lower)
.df <- .df[!duplicated(.df[, c("x", "z")]), ]
.df <- .fit <- data.frame(.fit, .df[, c("z"), drop = FALSE])
.df <- .fit <- rbind(unique(data.frame(x = 0, y = 1, nrisk = NA, nevent = NA, 
    ncensor = NA, upper = 1, lower = 1, .df[, c("z"), drop = FALSE])), .fit)
.cens <- subset(.fit, ncensor == 1)
.tmp1 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) max(d$nrisk, 
    na.rm = TRUE))))
.tmp1$x <- 0
.nrisk <- .tmp1
for (i in 1:3) {
    .df <- subset(.fit, x < 7 * i)
    .tmp2 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) if (all(is.na(d$nrisk))) 
        NA else min(d$nrisk - d$nevent - d$ncensor, na.rm = TRUE))))
    .tmp2$x <- 7 * i
    .tmp2$Freq[is.na(.tmp2$Freq)] <- .tmp1$Freq[is.na(.tmp2$Freq)]
    .tmp1 <- .tmp2
    .nrisk <- rbind(.nrisk, .tmp2)
}
.nrisk$y <- rep(seq(0.175, 0.025, -0.05), 4)
.plot <- ggplot(data = .fit, aes(x = x, y = y, colour = z)) + geom_step(data = subset(.fit, 
    !is.na(upper)), aes(y = upper), size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, 
    na.rm = FALSE) + geom_step(data = subset(.fit, !is.na(lower)), aes(y = lower), 
    size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, na.rm = FALSE) + geom_step(size = 1.5) + 
    geom_linerange(data = .cens, aes(x = x, ymin = y, ymax = y + 0.02), size = 1.5) + 
    geom_text(data = .pval, aes(y = y, x = x, label = label), colour = "black", 
        hjust = 0, vjust = -0.5, parse = TRUE, show.legend = FALSE, size = 14 * 
            0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 21, 
    by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1), expand = c(0.01, 
    0)) + scale_colour_brewer(palette = "Set1") + xlab("Tempo em anos de abono") + 
    ylab("Probabilidade de S(t)") + labs(colour = "id_ini_serv_pub") + labs(title = "Estimador de Kaplan-Meier") + 
    theme_grey(base_size = 14, base_family = "sans") + theme(legend.position = c(1, 
    1), legend.justification = c(1, 1), legend.background = element_rect(fill = "transparent"))
.nrisk$y <- ((.nrisk$y - 0.025)/(max(.nrisk$y) - 0.025) + 0.125) * 0.8
.plot2 <- ggplot(data = .nrisk, aes(x = x, y = y, label = Freq, colour = z)) + 
    geom_text(size = 14 * 0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 
    21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1)) + 
    scale_colour_brewer(palette = "Set1") + ylab("Probabilidade de S(t)") + 
    RcmdrPlugin.KMggplot2::theme_natrisk(theme_grey, 14, "sans")
.plot3 <- ggplot(data = subset(.nrisk, x == 0), aes(x = x, y = y, label = z, 
    colour = z)) + geom_text(hjust = 0, size = 14 * 0.282, family = "sans") + 
    scale_x_continuous(limits = c(-5, 5)) + scale_y_continuous(limits = c(0, 
    1)) + scale_colour_brewer(palette = "Set1") + RcmdrPlugin.KMggplot2::theme_natrisk21(theme_grey, 
    14, "sans")
.plotb <- ggplot(.df, aes(x = x, y = y)) + geom_blank() + RcmdrPlugin.KMggplot2::theme_natriskbg(theme_grey, 
    14, "sans")
grid::grid.newpage()
grid::pushViewport(grid::viewport(layout = grid::grid.layout(2, 2, heights = unit(c(1, 
    4), c("null", "lines")), widths = unit(c(4, 1), c("lines", "null")))))
print(.plotb, vp = grid::viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))
print(.plot, vp = grid::viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(.plot2, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1:2))
print(.plot3, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1))

.plot <- recordPlot()
print(.plot)
rm(.df, .fit, .pval, .ppval, .cens, .tmp1, .tmp2, .nrisk, .plot, .plot2, .plot3, 
    .plotb)
.Survfit <- survfit(Surv(tempo, status, type = "right") ~ id_ini_serv_pub, conf.type = "log", 
    conf.int = 0.95, type = "kaplan-meier", error = "greenwood", data = mes0619)
.Survfit
Call: survfit(formula = Surv(tempo, status, type = "right") ~ id_ini_serv_pub, 
    data = mes0619, error = "greenwood", conf.type = "log", conf.int = 0.95, 
    type = "kaplan-meier")

                                       n events median 0.95LCL 0.95UCL
id_ini_serv_pub=entre 20 a 30 anos 10189   4878   7.93    7.65    8.17
id_ini_serv_pub=entre 30 e 40 anos  5214   3272   6.39    6.23    6.61
id_ini_serv_pub=mais de 40 anos     1378    890   6.65    6.29    7.14
id_ini_serv_pub=menos de 20 anos    1198    469   7.78    7.10    8.70
quantile(.Survfit, quantiles = c(0.25, 0.5, 0.75))
$quantile
                                         25       50       75
id_ini_serv_pub=entre 20 a 30 anos 3.413699 7.926027 15.09589
id_ini_serv_pub=entre 30 e 40 anos 2.802740 6.389041 11.56712
id_ini_serv_pub=mais de 40 anos    2.975342 6.652055 10.04110
id_ini_serv_pub=menos de 20 anos   3.358904 7.778082 15.40000

$lower
                                         25       50        75
id_ini_serv_pub=entre 20 a 30 anos 3.249315 7.646575 14.731507
id_ini_serv_pub=entre 30 e 40 anos 2.597260 6.232877 11.213699
id_ini_serv_pub=mais de 40 anos    2.778082 6.290411  9.536986
id_ini_serv_pub=menos de 20 anos   3.128767 7.104110 13.942466

$upper
                                         25       50       75
id_ini_serv_pub=entre 20 a 30 anos 3.556164 8.172603 15.32055
id_ini_serv_pub=entre 30 e 40 anos 2.978082 6.605479 12.20274
id_ini_serv_pub=mais de 40 anos    3.383562 7.139726 10.72055
id_ini_serv_pub=menos de 20 anos   3.810959 8.704110       NA
remove(.Survfit)
require("ggplot2")
.df <- na.omit(data.frame(x = mes0619$tempo, y = mes0619$status, z = mes0619$Tipo_Regiao))
.df <- .df[do.call(order, .df[, c("z", "x"), drop = FALSE]), , drop = FALSE]
.fit <- survival::survfit(survival::Surv(time = x, event = y, type = "right") ~ 
    z, .df)
.pval <- plyr::ddply(.df, plyr::.(), function(x) {
    data.frame(x = 0, y = 0, df = 2, chisq = survival::survdiff(survival::Surv(time = x, 
        event = y, type = "right") ~ z, x)$chisq)
})
.pval$label <- paste0("paste(italic(p), \" = ", signif(1 - pchisq(.pval$chisq, 
    .pval$df), 3), "\")")
.fit <- data.frame(x = .fit$time, y = .fit$surv, nrisk = .fit$n.risk, nevent = .fit$n.event, 
    ncensor = .fit$n.censor, upper = .fit$upper, lower = .fit$lower)
.df <- .df[!duplicated(.df[, c("x", "z")]), ]
.df <- .fit <- data.frame(.fit, .df[, c("z"), drop = FALSE])
.df <- .fit <- rbind(unique(data.frame(x = 0, y = 1, nrisk = NA, nevent = NA, 
    ncensor = NA, upper = 1, lower = 1, .df[, c("z"), drop = FALSE])), .fit)
.cens <- subset(.fit, ncensor == 1)
.tmp1 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) max(d$nrisk, 
    na.rm = TRUE))))
.tmp1$x <- 0
.nrisk <- .tmp1
for (i in 1:3) {
    .df <- subset(.fit, x < 7 * i)
    .tmp2 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) if (all(is.na(d$nrisk))) 
        NA else min(d$nrisk - d$nevent - d$ncensor, na.rm = TRUE))))
    .tmp2$x <- 7 * i
    .tmp2$Freq[is.na(.tmp2$Freq)] <- .tmp1$Freq[is.na(.tmp2$Freq)]
    .tmp1 <- .tmp2
    .nrisk <- rbind(.nrisk, .tmp2)
}
.nrisk$y <- rep(seq(0.125, 0.025, -0.05), 4)
.plot <- ggplot(data = .fit, aes(x = x, y = y, colour = z)) + geom_step(data = subset(.fit, 
    !is.na(upper)), aes(y = upper), size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, 
    na.rm = FALSE) + geom_step(data = subset(.fit, !is.na(lower)), aes(y = lower), 
    size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, na.rm = FALSE) + geom_step(size = 1.5) + 
    geom_linerange(data = .cens, aes(x = x, ymin = y, ymax = y + 0.02), size = 1.5) + 
    geom_text(data = .pval, aes(y = y, x = x, label = label), colour = "black", 
        hjust = 0, vjust = -0.5, parse = TRUE, show.legend = FALSE, size = 14 * 
            0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 21, 
    by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1), expand = c(0.01, 
    0)) + scale_colour_brewer(palette = "Set1") + xlab("Tempo em anos de abono") + 
    ylab("Propabilidade de S(t)") + labs(colour = "Tipo_Regiao") + labs(title = "Estimador de Kaplan-Meier") + 
    theme_grey(base_size = 14, base_family = "sans") + theme(legend.position = c(1, 
    1), legend.justification = c(1, 1), legend.background = element_rect(fill = "transparent"))
.nrisk$y <- ((.nrisk$y - 0.025)/(max(.nrisk$y) - 0.025) + 0.125) * 0.8
.plot2 <- ggplot(data = .nrisk, aes(x = x, y = y, label = Freq, colour = z)) + 
    geom_text(size = 14 * 0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 
    21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1)) + 
    scale_colour_brewer(palette = "Set1") + ylab("Propabilidade de S(t)") + 
    RcmdrPlugin.KMggplot2::theme_natrisk(theme_grey, 14, "sans")
.plot3 <- ggplot(data = subset(.nrisk, x == 0), aes(x = x, y = y, label = z, 
    colour = z)) + geom_text(hjust = 0, size = 14 * 0.282, family = "sans") + 
    scale_x_continuous(limits = c(-5, 5)) + scale_y_continuous(limits = c(0, 
    1)) + scale_colour_brewer(palette = "Set1") + RcmdrPlugin.KMggplot2::theme_natrisk21(theme_grey, 
    14, "sans")
.plotb <- ggplot(.df, aes(x = x, y = y)) + geom_blank() + RcmdrPlugin.KMggplot2::theme_natriskbg(theme_grey, 
    14, "sans")
grid::grid.newpage()
grid::pushViewport(grid::viewport(layout = grid::grid.layout(2, 2, heights = unit(c(1, 
    3.5), c("null", "lines")), widths = unit(c(4, 1), c("lines", "null")))))
print(.plotb, vp = grid::viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))
print(.plot, vp = grid::viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(.plot2, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1:2))
print(.plot3, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1))

.plot <- recordPlot()
print(.plot)
rm(.df, .fit, .pval, .ppval, .cens, .tmp1, .tmp2, .nrisk, .plot, .plot2, .plot3, 
    .plotb)
.Survfit <- survfit(Surv(tempo, status, type = "right") ~ Tipo_Regiao, conf.type = "log", 
    conf.int = 0.95, type = "kaplan-meier", error = "greenwood", data = mes0619)
.Survfit
Call: survfit(formula = Surv(tempo, status, type = "right") ~ Tipo_Regiao, 
    data = mes0619, error = "greenwood", conf.type = "log", conf.int = 0.95, 
    type = "kaplan-meier")

                              n events median 0.95LCL 0.95UCL
Tipo_Regiao=Cidade_Grande  9122   4661   7.84    7.60    8.10
Tipo_Regiao=Cidade_Média   7364   4036   6.58    6.39    6.81
Tipo_Regiao=Cidade_Pequena 1493    812   7.13    6.58    7.45
quantile(.Survfit, quantiles = c(0.25, 0.5, 0.75))
$quantile
                                 25       50       75
Tipo_Regiao=Cidade_Grande  3.572603 7.838356 14.24384
Tipo_Regiao=Cidade_Média   2.865753 6.575342 12.30411
Tipo_Regiao=Cidade_Pequena 3.139726 7.128767 12.42740

$lower
                                 25       50       75
Tipo_Regiao=Cidade_Grande  3.405479 7.597260 13.69589
Tipo_Regiao=Cidade_Média   2.736986 6.386301 11.56712
Tipo_Regiao=Cidade_Pequena 2.805479 6.578082 11.27945

$upper
                                 25       50       75
Tipo_Regiao=Cidade_Grande  3.726027 8.104110 14.75890
Tipo_Regiao=Cidade_Média   2.991781 6.810959 13.19452
Tipo_Regiao=Cidade_Pequena 3.454795 7.449315 14.22466
remove(.Survfit)
require("ggplot2")
.df <- na.omit(data.frame(x = mes0619$tempo, y = mes0619$status, z = mes0619$Desc_Renda_Bruta))
.df <- .df[do.call(order, .df[, c("z", "x"), drop = FALSE]), , drop = FALSE]
.fit <- survival::survfit(survival::Surv(time = x, event = y, type = "right") ~ 
    z, .df)
.pval <- plyr::ddply(.df, plyr::.(), function(x) {
    data.frame(x = 0, y = 0, df = 3, chisq = survival::survdiff(survival::Surv(time = x, 
        event = y, type = "right") ~ z, x)$chisq)
})
.pval$label <- paste0("paste(italic(p), \" = ", signif(1 - pchisq(.pval$chisq, 
    .pval$df), 3), "\")")
.fit <- data.frame(x = .fit$time, y = .fit$surv, nrisk = .fit$n.risk, nevent = .fit$n.event, 
    ncensor = .fit$n.censor, upper = .fit$upper, lower = .fit$lower)
.df <- .df[!duplicated(.df[, c("x", "z")]), ]
.df <- .fit <- data.frame(.fit, .df[, c("z"), drop = FALSE])
.df <- .fit <- rbind(unique(data.frame(x = 0, y = 1, nrisk = NA, nevent = NA, 
    ncensor = NA, upper = 1, lower = 1, .df[, c("z"), drop = FALSE])), .fit)
.cens <- subset(.fit, ncensor == 1)
.tmp1 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) max(d$nrisk, 
    na.rm = TRUE))))
.tmp1$x <- 0
.nrisk <- .tmp1
for (i in 1:3) {
    .df <- subset(.fit, x < 7 * i)
    .tmp2 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) if (all(is.na(d$nrisk))) 
        NA else min(d$nrisk - d$nevent - d$ncensor, na.rm = TRUE))))
    .tmp2$x <- 7 * i
    .tmp2$Freq[is.na(.tmp2$Freq)] <- .tmp1$Freq[is.na(.tmp2$Freq)]
    .tmp1 <- .tmp2
    .nrisk <- rbind(.nrisk, .tmp2)
}
.nrisk$y <- rep(seq(0.175, 0.025, -0.05), 4)
.plot <- ggplot(data = .fit, aes(x = x, y = y, colour = z)) + geom_step(data = subset(.fit, 
    !is.na(upper)), aes(y = upper), size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, 
    na.rm = FALSE) + geom_step(data = subset(.fit, !is.na(lower)), aes(y = lower), 
    size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, na.rm = FALSE) + geom_step(size = 1.5) + 
    geom_linerange(data = .cens, aes(x = x, ymin = y, ymax = y + 0.02), size = 1.5) + 
    geom_text(data = .pval, aes(y = y, x = x, label = label), colour = "black", 
        hjust = 0, vjust = -0.5, parse = TRUE, show.legend = FALSE, size = 14 * 
            0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 21, 
    by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1), expand = c(0.01, 
    0)) + scale_colour_brewer(palette = "Set1") + xlab("Time from entry") + 
    ylab("Proportion of survival") + labs(colour = "Desc_Renda_Bruta") + theme_grey(base_size = 14, 
    base_family = "sans") + theme(legend.position = c(1, 1), legend.justification = c(1, 
    1), legend.background = element_rect(fill = "transparent"))
.nrisk$y <- ((.nrisk$y - 0.025)/(max(.nrisk$y) - 0.025) + 0.125) * 0.8
.plot2 <- ggplot(data = .nrisk, aes(x = x, y = y, label = Freq, colour = z)) + 
    geom_text(size = 14 * 0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 
    21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1)) + 
    scale_colour_brewer(palette = "Set1") + ylab("Proportion of survival") + 
    RcmdrPlugin.KMggplot2::theme_natrisk(theme_grey, 14, "sans")
.plot3 <- ggplot(data = subset(.nrisk, x == 0), aes(x = x, y = y, label = z, 
    colour = z)) + geom_text(hjust = 0, size = 14 * 0.282, family = "sans") + 
    scale_x_continuous(limits = c(-5, 5)) + scale_y_continuous(limits = c(0, 
    1)) + scale_colour_brewer(palette = "Set1") + RcmdrPlugin.KMggplot2::theme_natrisk21(theme_grey, 
    14, "sans")
.plotb <- ggplot(.df, aes(x = x, y = y)) + geom_blank() + RcmdrPlugin.KMggplot2::theme_natriskbg(theme_grey, 
    14, "sans")
grid::grid.newpage()
grid::pushViewport(grid::viewport(layout = grid::grid.layout(2, 2, heights = unit(c(1, 
    4), c("null", "lines")), widths = unit(c(4, 1), c("lines", "null")))))
print(.plotb, vp = grid::viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))
print(.plot, vp = grid::viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(.plot2, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1:2))
print(.plot3, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1))

.plot <- recordPlot()
print(.plot)
rm(.df, .fit, .pval, .ppval, .cens, .tmp1, .tmp2, .nrisk, .plot, .plot2, .plot3, 
    .plotb)
.Survfit <- survfit(Surv(tempo, status, type = "right") ~ Desc_Renda_Bruta, 
    conf.type = "log", conf.int = 0.95, type = "kaplan-meier", error = "greenwood", 
    data = mes0619)
.Survfit
Call: survfit(formula = Surv(tempo, status, type = "right") ~ Desc_Renda_Bruta, 
    data = mes0619, error = "greenwood", conf.type = "log", conf.int = 0.95, 
    type = "kaplan-meier")

                                     n events median 0.95LCL 0.95UCL
Desc_Renda_Bruta=até 20%         11157   7189   5.82    5.70    6.02
Desc_Renda_Bruta=entre 20% a 30%  3743   1863   8.12    7.67    8.46
Desc_Renda_Bruta=entre 30% a 40%  2529    321     NA      NA      NA
Desc_Renda_Bruta=mais de 40%       550    136  14.61   10.76      NA
quantile(.Survfit, quantiles = c(0.25, 0.5, 0.75))
$quantile
                                        25        50       75
Desc_Renda_Bruta=até 20%          2.487671  5.819178 10.45753
Desc_Renda_Bruta=entre 20% a 30%  3.589041  8.115068 14.45479
Desc_Renda_Bruta=entre 30% a 40% 12.183562        NA       NA
Desc_Renda_Bruta=mais de 40%      7.306849 14.605479       NA

$lower
                                        25        50       75
Desc_Renda_Bruta=até 20%          2.369863  5.698630 10.25205
Desc_Renda_Bruta=entre 20% a 30%  3.290411  7.668493 13.84110
Desc_Renda_Bruta=entre 30% a 40% 11.142466        NA       NA
Desc_Renda_Bruta=mais de 40%      6.246575 10.761644       NA

$upper
                                        25       50       75
Desc_Renda_Bruta=até 20%          2.597260 6.019178 10.71507
Desc_Renda_Bruta=entre 20% a 30%  3.860274 8.457534 15.20274
Desc_Renda_Bruta=entre 30% a 40% 15.175342       NA       NA
Desc_Renda_Bruta=mais de 40%      8.917808       NA       NA
remove(.Survfit)
require("ggplot2")
.df <- na.omit(data.frame(x = mes0619$tempo, y = mes0619$status, z = mes0619$Qtde_dependentes))
.df <- .df[do.call(order, .df[, c("z", "x"), drop = FALSE]), , drop = FALSE]
.fit <- survival::survfit(survival::Surv(time = x, event = y, type = "right") ~ 
    z, .df)
.pval <- plyr::ddply(.df, plyr::.(), function(x) {
    data.frame(x = 0, y = 0, df = 2, chisq = survival::survdiff(survival::Surv(time = x, 
        event = y, type = "right") ~ z, x)$chisq)
})
.pval$label <- paste0("paste(italic(p), \" = ", signif(1 - pchisq(.pval$chisq, 
    .pval$df), 3), "\")")
.fit <- data.frame(x = .fit$time, y = .fit$surv, nrisk = .fit$n.risk, nevent = .fit$n.event, 
    ncensor = .fit$n.censor, upper = .fit$upper, lower = .fit$lower)
.df <- .df[!duplicated(.df[, c("x", "z")]), ]
.df <- .fit <- data.frame(.fit, .df[, c("z"), drop = FALSE])
.df <- .fit <- rbind(unique(data.frame(x = 0, y = 1, nrisk = NA, nevent = NA, 
    ncensor = NA, upper = 1, lower = 1, .df[, c("z"), drop = FALSE])), .fit)
.cens <- subset(.fit, ncensor == 1)
.tmp1 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) max(d$nrisk, 
    na.rm = TRUE))))
.tmp1$x <- 0
.nrisk <- .tmp1
for (i in 1:3) {
    .df <- subset(.fit, x < 7 * i)
    .tmp2 <- data.frame(as.table(by(.df, .df[, c("z"), drop = FALSE], function(d) if (all(is.na(d$nrisk))) 
        NA else min(d$nrisk - d$nevent - d$ncensor, na.rm = TRUE))))
    .tmp2$x <- 7 * i
    .tmp2$Freq[is.na(.tmp2$Freq)] <- .tmp1$Freq[is.na(.tmp2$Freq)]
    .tmp1 <- .tmp2
    .nrisk <- rbind(.nrisk, .tmp2)
}
.nrisk$y <- rep(seq(0.125, 0.025, -0.05), 4)
.plot <- ggplot(data = .fit, aes(x = x, y = y, colour = z)) + geom_step(data = subset(.fit, 
    !is.na(upper)), aes(y = upper), size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, 
    na.rm = FALSE) + geom_step(data = subset(.fit, !is.na(lower)), aes(y = lower), 
    size = 1, lty = 2, alpha = 0.5, show.legend = FALSE, na.rm = FALSE) + geom_step(size = 1.5) + 
    geom_linerange(data = .cens, aes(x = x, ymin = y, ymax = y + 0.02), size = 1.5) + 
    geom_text(data = .pval, aes(y = y, x = x, label = label), colour = "black", 
        hjust = 0, vjust = -0.5, parse = TRUE, show.legend = FALSE, size = 14 * 
            0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 21, 
    by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1), expand = c(0.01, 
    0)) + scale_colour_brewer(palette = "Set1") + xlab("Time from entry") + 
    ylab("Proportion of survival") + labs(colour = "Qtde_dependentes") + theme_grey(base_size = 14, 
    base_family = "sans") + theme(legend.position = c(1, 1), legend.justification = c(1, 
    1), legend.background = element_rect(fill = "transparent"))
.nrisk$y <- ((.nrisk$y - 0.025)/(max(.nrisk$y) - 0.025) + 0.125) * 0.8
.plot2 <- ggplot(data = .nrisk, aes(x = x, y = y, label = Freq, colour = z)) + 
    geom_text(size = 14 * 0.282, family = "sans") + scale_x_continuous(breaks = seq(0, 
    21, by = 7), limits = c(0, 21)) + scale_y_continuous(limits = c(0, 1)) + 
    scale_colour_brewer(palette = "Set1") + ylab("Proportion of survival") + 
    RcmdrPlugin.KMggplot2::theme_natrisk(theme_grey, 14, "sans")
.plot3 <- ggplot(data = subset(.nrisk, x == 0), aes(x = x, y = y, label = z, 
    colour = z)) + geom_text(hjust = 0, size = 14 * 0.282, family = "sans") + 
    scale_x_continuous(limits = c(-5, 5)) + scale_y_continuous(limits = c(0, 
    1)) + scale_colour_brewer(palette = "Set1") + RcmdrPlugin.KMggplot2::theme_natrisk21(theme_grey, 
    14, "sans")
.plotb <- ggplot(.df, aes(x = x, y = y)) + geom_blank() + RcmdrPlugin.KMggplot2::theme_natriskbg(theme_grey, 
    14, "sans")
grid::grid.newpage()
grid::pushViewport(grid::viewport(layout = grid::grid.layout(2, 2, heights = unit(c(1, 
    3.5), c("null", "lines")), widths = unit(c(4, 1), c("lines", "null")))))
print(.plotb, vp = grid::viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))
print(.plot, vp = grid::viewport(layout.pos.row = 1, layout.pos.col = 1:2))
print(.plot2, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1:2))
print(.plot3, vp = grid::viewport(layout.pos.row = 2, layout.pos.col = 1))

.plot <- recordPlot()
print(.plot)
rm(.df, .fit, .pval, .ppval, .cens, .tmp1, .tmp2, .nrisk, .plot, .plot2, .plot3, 
    .plotb)
.Survfit <- survfit(Surv(tempo, status, type = "right") ~ Qtde_dependentes, 
    conf.type = "log", conf.int = 0.95, type = "kaplan-meier", error = "greenwood", 
    data = mes0619)
.Survfit
Call: survfit(formula = Surv(tempo, status, type = "right") ~ Qtde_dependentes, 
    data = mes0619, error = "greenwood", conf.type = "log", conf.int = 0.95, 
    type = "kaplan-meier")

                                  n events median 0.95LCL 0.95UCL
Qtde_dependentes=até dois      6884   3382   7.41    7.19    7.73
Qtde_dependentes=dois ou mais   543    209   6.78    5.85    8.96
Qtde_dependentes=Nenhum       10552   5918   7.14    6.99    7.27
quantile(.Survfit, quantiles = c(0.25, 0.5, 0.75))
$quantile
                                    25       50       75
Qtde_dependentes=até dois     3.383562 7.405479 13.43836
Qtde_dependentes=dois ou mais 2.934247 6.780822 12.45205
Qtde_dependentes=Nenhum       3.093151 7.136986 13.45479

$lower
                                    25       50       75
Qtde_dependentes=até dois     3.186301 7.191781 12.68767
Qtde_dependentes=dois ou mais 2.600000 5.852055 11.17534
Qtde_dependentes=Nenhum       2.958904 6.989041 13.09589

$upper
                                    25       50       75
Qtde_dependentes=até dois     3.558904 7.731507 14.11233
Qtde_dependentes=dois ou mais 3.375342 8.958904       NA
Qtde_dependentes=Nenhum       3.224658 7.271233 14.02466
remove(.Survfit)

Regressão Logística

indices <- sample(1:nrow(mes0619), floor(nrow(mes0619) * 0.8))
treino <- mes0619[indices, ]
teste <- mes0619[-indices, ]

GLM.1 <- glm(status ~ Qtde_dependentes + SEXO + Tipo_Regiao + Desc_Renda_Bruta + 
    id_ini_serv_pub, family = binomial(logit), data = treino)
summary(GLM.1)

Call:
glm(formula = status ~ Qtde_dependentes + SEXO + Tipo_Regiao + 
    Desc_Renda_Bruta + id_ini_serv_pub, family = binomial(logit), 
    data = treino)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.7177  -1.1940   0.7611   0.9976   2.2620  

Coefficients:
                                   Estimate Std. Error z value Pr(>|z|)
(Intercept)                        0.212274   0.045813   4.633 3.60e-06
Qtde_dependentesdois ou mais      -0.296489   0.113041  -2.623 0.008720
Qtde_dependentesNenhum             0.145172   0.038914   3.731 0.000191
SEXOM                             -0.002498   0.038728  -0.064 0.948580
Tipo_RegiaoCidade_Média            0.226716   0.038393   5.905 3.52e-09
Tipo_RegiaoCidade_Pequena          0.349205   0.068397   5.106 3.30e-07
Desc_Renda_Brutaentre 20% a 30%   -0.545131   0.043284 -12.594  < 2e-16
Desc_Renda_Brutaentre 30% a 40%   -2.390953   0.069970 -34.171  < 2e-16
Desc_Renda_Brutamais de 40%       -1.685908   0.115851 -14.552  < 2e-16
id_ini_serv_pubentre 30 e 40 anos  0.508986   0.042291  12.035  < 2e-16
id_ini_serv_pubmais de 40 anos     0.448215   0.070502   6.357 2.05e-10
id_ini_serv_pubmenos de 20 anos   -0.271858   0.074741  -3.637 0.000275
                                     
(Intercept)                       ***
Qtde_dependentesdois ou mais      ** 
Qtde_dependentesNenhum            ***
SEXOM                                
Tipo_RegiaoCidade_Média           ***
Tipo_RegiaoCidade_Pequena         ***
Desc_Renda_Brutaentre 20% a 30%   ***
Desc_Renda_Brutaentre 30% a 40%   ***
Desc_Renda_Brutamais de 40%       ***
id_ini_serv_pubentre 30 e 40 anos ***
id_ini_serv_pubmais de 40 anos    ***
id_ini_serv_pubmenos de 20 anos   ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 19887  on 14382  degrees of freedom
Residual deviance: 17562  on 14371  degrees of freedom
AIC: 17586

Number of Fisher Scoring iterations: 4
exp(coef(GLM.1))
                      (Intercept)      Qtde_dependentesdois ou mais 
                       1.23648676                        0.74342387 
           Qtde_dependentesNenhum                             SEXOM 
                       1.15623874                        0.99750550 
          Tipo_RegiaoCidade_Média         Tipo_RegiaoCidade_Pequena 
                       1.25447390                        1.41793977 
  Desc_Renda_Brutaentre 20% a 30%   Desc_Renda_Brutaentre 30% a 40% 
                       0.57976605                        0.09154237 
      Desc_Renda_Brutamais de 40% id_ini_serv_pubentre 30 e 40 anos 
                       0.18527603                        1.66360325 
   id_ini_serv_pubmais de 40 anos   id_ini_serv_pubmenos de 20 anos 
                       1.56551583                        0.76196259 
modfinal <- step(GLM.1, scope = list(lower = ~1))
Start:  AIC=17586.22
status ~ Qtde_dependentes + SEXO + Tipo_Regiao + Desc_Renda_Bruta + 
    id_ini_serv_pub

                   Df Deviance   AIC
- SEXO              1    17562 17584
<none>                   17562 17586
- Qtde_dependentes  2    17588 17608
- Tipo_Regiao       2    17611 17631
- id_ini_serv_pub   3    17760 17778
- Desc_Renda_Bruta  3    19374 19392

Step:  AIC=17584.22
status ~ Qtde_dependentes + Tipo_Regiao + Desc_Renda_Bruta + 
    id_ini_serv_pub

                   Df Deviance   AIC
<none>                   17562 17584
- Qtde_dependentes  2    17589 17607
- Tipo_Regiao       2    17611 17629
- id_ini_serv_pub   3    17769 17785
- Desc_Renda_Bruta  3    19378 19394
summary(modfinal)

Call:
glm(formula = status ~ Qtde_dependentes + Tipo_Regiao + Desc_Renda_Bruta + 
    id_ini_serv_pub, family = binomial(logit), data = treino)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.7172  -1.1937   0.7607   0.9980   2.2616  

Coefficients:
                                  Estimate Std. Error z value Pr(>|z|)    
(Intercept)                        0.21105    0.04172   5.059 4.22e-07 ***
Qtde_dependentesdois ou mais      -0.29675    0.11297  -2.627 0.008617 ** 
Qtde_dependentesNenhum             0.14574    0.03790   3.845 0.000120 ***
Tipo_RegiaoCidade_Média            0.22668    0.03839   5.905 3.53e-09 ***
Tipo_RegiaoCidade_Pequena          0.34905    0.06835   5.106 3.28e-07 ***
Desc_Renda_Brutaentre 20% a 30%   -0.54512    0.04328 -12.594  < 2e-16 ***
Desc_Renda_Brutaentre 30% a 40%   -2.39105    0.06996 -34.180  < 2e-16 ***
Desc_Renda_Brutamais de 40%       -1.68653    0.11545 -14.608  < 2e-16 ***
id_ini_serv_pubentre 30 e 40 anos  0.50857    0.04180  12.167  < 2e-16 ***
id_ini_serv_pubmais de 40 anos     0.44743    0.06944   6.444 1.17e-10 ***
id_ini_serv_pubmenos de 20 anos   -0.27159    0.07462  -3.639 0.000273 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 19887  on 14382  degrees of freedom
Residual deviance: 17562  on 14372  degrees of freedom
AIC: 17584

Number of Fisher Scoring iterations: 4
tabela <- table(GLM.1$fitted.values > 0.55, treino$status)
tabela %>% kable()
0 1
FALSE 3512 1585
TRUE 3249 6037
sum(diag(tabela))/sum(tabela)
[1] 0.6639088
result <- predict(modfinal, treino, "response")
pred <- prediction(result, treino$status)
perf <- performance(pred, "fpr", "fnr")
plot(perf, print.cutoffs.at = seq(0.1, 0.9, by = 0.05))

LS0tDQp0aXRsZTogIkRpYWduw7NzdGljbyBTb2JyZSBhIEFwb3NlbnRhZG9yaWEgbm8gU2VydmnDp28gUMO6YmxpY28iDQpzdWJ0aXRsZTogIkFwbGljYcOnw6NvIGRlIFJlZ3Jlc3PDo28gTG9nw61zdGljYSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgICBodG1sX2RvY3VtZW50Og0KICAgICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCmBgYHtyfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwcm9tcHQ9RkFMU0UsICAgICAgdGlkeT1UUlVFLCBjb21tZW50PU5BKQ0KYGBgDQoNCg0KDQpgYGB7ciBrbml0cl9pbml0LCBlY2hvPUZBTFNFfQ0KDQoNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHJtZGZvcm1hdHMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShycGl2b3RUYWJsZSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoYWJpbmQsIHBvcz0zOCkNCmxpYnJhcnkoZTEwNzEsIHBvcz0zOSkNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShSY21kck1pc2MpDQpsaWJyYXJ5KHN1cnZpdmFsKQ0KbGlicmFyeShnZ2ZvcnRpZnkpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KFJPQ1IpDQpgYGANCg0KIyMgSW50cm9kdcOnw6NvDQoNCk5vIHNlcnZpw6dvIHDDumJsaWNvIMOpIGNvbXVtIHF1ZSBhbGd1bnMgc2Vydmlkb3JlcyBuw6NvIGFwb3NlbnRhbSBuYSBkYXRhIGVtIHF1ZSBjb21lw6dhIGEgdGVyIG8gZGlyZWl0byBhIGFwb3NlbnRhZG9yaWEgZSBwZXJtYW5lY2VtIG5vIHRyYWJhbGhvIGF0w6kgbyB0ZW1wbyBkYSBpZGFkZSBjb21wdWxzw7NyaWEgcmVjZWJlbmRvIHVtIGFib25vLiBEZXNzYSBmb3JtYSwgbyBvYmpldGl2byBkbyBlc3R1ZG8gY29uc2lzdGUgbmEgZXhwbG9yYcOnw6NvIGRhIHRlb3JpYSBkZSBhbsOhbGlzZSBkZSByZWdyZXNzw6NvIGxvZ8Otc3RpY2EgcGFyYSBkZWxpbmVhciBvIHBlcmZpbCBkb3Mgc2Vydmlkb3JlcyBxdWUgYWRxdWlyZW0gbyBkaXJlaXRvIGFvIGFib25vIHNhbGFyaWFsIGUgZGVjaWRlbSBzZSBjb250aW51YW0gdHJhYmFsaGFuZG8gPSAwIG91IG7Do28gPSAxLCBzaXR1YcOnw6NvIHF1ZSBzZXLDoSBhIHZhcmnDoXZlbCByZXNwb3N0YSBkZSBpbnRlcmVzc2UgbmVzdGUgY2Fzby4NCg0KDQojIyBCYXNlIGRlIERhZG9zDQpQYXJhIHN1YnNpZGlhciBlc3RlIGVzdHVkbywgZm9yYW0gY29sZXRhZGFzIGluZm9ybWHDp8O1ZXMgZG8gRGF0YSBXYXJlaG91c2UgZG8gU2lzdGVtYSBJbnRlZ3JhZG8gZGUgQWRtaW5pc3RyYcOnw6NvIGRlIFBlc3NvYWwgLSBEVyBTSUFQRSBkb3Mgc2Vydmlkb3JlcyBww7pibGljb3MgZG8gTWluaXN0w6lyaW8gZGEgRWNvbm9taWEgLSBNRSwgYXRpdm9zIGUgaW5hdGl2b3Mgbm8gcGVyw61vZG8gZGUgamFuZWlybyBkZSAyMDE5IGEganVsaG8gZGUgMjAxOS4NCg0KQXMgaW5mb3JtYcOnw7VlcyBleHRyYcOtZGFzIGZvcmFtOg0KDQrigKIgTm9tZSDigKIgU2V4byDigKIgQ1BGIChjaGF2ZSBwcmltw6FyaWEpIOKAoiBNYXRyaWN1bGEgU0lBUEUg4oCiIENMQVNTRV9DQVJHTyDigKIgUEFEUkFPX0NBUkdPIOKAoiBTSVRVQUNBT19WSU5DVUxPIOKAoiBSRUdJTUVfSlVSSURJQ08g4oCiIEpPUk5BREFfREVfVFJBQkFMSE8g4oCiIFJlbXVuZXJhw6fDo28g4oCiIEFuby9Nw6pzIGluaWNpYWwgZG8gYWJvbm8gZGUgcGVybWFuw6puY2lhIOKAoiBWYWxvciBBYm9ubyAoY2FzbyB0ZW5oYSkg4oCiIFRvZGFzIGFzIGdyYXRpZmljYcOnw7VlcyBlIGZ1bsOnw7VlcyBjb21pc3Npb25hZGFzIOKAoiBGdW7Dp8O1ZXMg4oCTIFZQTkkg4oCiIFF1YW50aWRhZGUgZGUgZGVwZW5kZW50ZXMg4oCiIERlc2NyacOnw6NvIGRvIGNhcmdvIGVtcHJlZ28g4oCiIE7DrXZlbCBkZSBFc2NvbGFyaWRhZGUg4oCiIERlbm9taW5hw6fDo28gZG8gw7NyZ8OjbyBkZSBhdHVhw6fDo28g4oCiIFVGIGRhIFVQQUcgZGUgdmluY3VsYcOnw6NvIOKAoiBEZW5vbWluYcOnw6NvIHVuaWRhZGUgb3JnYW5pemFjaW9uYWwg4oCiIE9SR1NVUF9FWEVSQ0lDSU8g4oCiIFVGIGRhIFJlc2lkw6puY2lhIOKAoiBDaWRhZGUgZGEgcmVzaWTDqm5jaWEg4oCiIFNpdHVhw6fDo28gc2Vydmlkb3Ig4oCiIFRpcG8gREUgQXBvc2VudGFkb3JpYSDigKIgRGF0YSBpbmdyZXNzbyBubyBzZXJ2acOnbyBww7pibGljbyDigKIgRGF0YSBkZSBuYXNjaW1lbnRvIOKAoiBEQVRBIG9jb3Jyw6puY2lhIGluYXRpdmlkYWRlDQoNCg0KIyMjIERlc2NyaXRpdmFzIGRvcyBkYWRvcw0KDQpJbmljaWFsbWVudGUsIHNlbGVjaW9ub3Utc2UgbyDDumx0aW1vIG3DqnMgZGVzdGEgYmFzZSBkZSBkYWRvcywganVuaG8gZGUgMjAxOSwgZSBidXNjb3Ugb3MgdGVtcG9zIGluaWNpYWlzIHBhcmEgbyBlc3R1ZG8sIG91IHNlamEsIGEgZGF0YSBkZSBpbsOtY2lvIGRvIGFib25vIGUsIHBhcmEgb3MgY2Fzb3MgZGEgb2NvcnLDqm5jaWEgZG8gZXZlbnRvIGRlIGFwb3NlbnRhZG9yaWFzLCBidXNjb3Utc2UgYSBkYXRhIGRlc3RlIGZhdG8uIA0KDQpgYGB7cn0NCg0KbWVzMDYxOSA8LSByZWFkLmNzdjIoImRhZG9zLmNzdiIpDQptZXMwNjE5ICU+JSBEVDo6ZGF0YXRhYmxlKCkNCg0KYGBgDQoNCg0KYGBge3J9DQpzdW1tYXJ5KG1lczA2MTlbLC1jKDEsMildKSANCg0KYGBgDQoNCg0KDQojIyBFeHBsb3Jhw6fDo28gZG9zIERhZG9zIGRlIFNvYnJldml2w6puY2lhIC0gRXN0aW1hZG9yIEthcGxhbi1NZWllcg0KDQoNCkEgcGFydGlyIGRvIEVzdGltYWRvciBkZSBLYXBsYW4tTWVpZXIgw6kgcG9zc8OtdmVsIG9ic2VydmFyIG8gdGVtcG8gbWVkaWFubyBkZSA3LjY2IGFub3MgcXVlIG9zIHNlcnZpZG9yZXMgZW0gYWJvbm8gc2FsYXJpYWwgcGVybWFuZWNlbSBubyB0cmFiYWxobyBhdMODwqkgZGVjaWRpcmVtIGFwb3NlbnRhcmVtLg0KDQoNCmBgYHtyfQ0KcmVxdWlyZSgiZ2dwbG90MiIpDQouZGYgPC0gbmEub21pdChkYXRhLmZyYW1lKHggPSBtZXMwNjE5JHRlbXBvLCB5ID0gbWVzMDYxOSRzdGF0dXMsIHogPSBmYWN0b3IoIkF0IHJpc2siKSkpDQouZGYgPC0gLmRmW2RvLmNhbGwob3JkZXIsIC5kZlssIGMoInoiLCAieCIpLCBkcm9wID0gRkFMU0VdKSwgLCBkcm9wID0gRkFMU0VdDQouZml0IDwtIHN1cnZpdmFsOjpzdXJ2Zml0KHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSAicmlnaHQiKSB+IHosIC5kZikNCi5maXQgPC0gZGF0YS5mcmFtZSh4ID0gLmZpdCR0aW1lLCB5ID0gLmZpdCRzdXJ2LCBucmlzayA9IC5maXQkbi5yaXNrLCBuZXZlbnQgPSAuZml0JG4uZXZlbnQsIG5jZW5zb3I9IA0KICAuZml0JG4uY2Vuc29yLCB1cHBlciA9IC5maXQkdXBwZXIsIGxvd2VyID0gLmZpdCRsb3dlcikNCi5kZiA8LSAuZGZbIWR1cGxpY2F0ZWQoLmRmWyxjKCJ4IiwgInoiKV0pLCBdDQouZGYgPC0gLmZpdCA8LSBkYXRhLmZyYW1lKC5maXQsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSkNCi5tZWQgPC0gcGx5cjo6ZGRwbHkoLmZpdCwgcGx5cjo6Lih6KSwgZnVuY3Rpb24oeCkgew0KZGF0YS5mcmFtZSgNCiBtZWRpYW4gPSBtaW4oc3Vic2V0KHgsIHkgPCAoMC41ICsgLk1hY2hpbmUkZG91YmxlLmVwc14wLjUpKSR4KQ0KKX0pDQouZGYgPC0gLmZpdCA8LSByYmluZCh1bmlxdWUoZGF0YS5mcmFtZSh4ID0gMCwgeSA9IDEsIG5yaXNrID0gTkEsIG5ldmVudCA9IE5BLCBuY2Vuc29yID0gTkEsIHVwcGVyID0gMSwgDQogIGxvd2VyID0gMSwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdKSksIC5maXQpDQouY2VucyA8LSBzdWJzZXQoLmZpdCwgbmNlbnNvciA9PSAxKQ0KLnRtcDEgPC0gZGF0YS5mcmFtZShhcy50YWJsZShieSguZGYsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSwgZnVuY3Rpb24oZCkgbWF4KGQkbnJpc2ssIG5hLnJtID0gDQogIFRSVUUpKSkpDQoudG1wMSR4IDwtIDANCi5ucmlzayA8LSAudG1wMQ0KZm9yIChpIGluIDE6Mykgey5kZiA8LSBzdWJzZXQoLmZpdCwgeCA8IDcgKiBpKTsgLnRtcDIgPC0gZGF0YS5mcmFtZShhcy50YWJsZShieSguZGYsIC5kZlssIGMoInoiKSwgZHJvcCANCiAgPSBGQUxTRV0sIGZ1bmN0aW9uKGQpIGlmIChhbGwoaXMubmEoZCRucmlzaykpKSBOQSBlbHNlIG1pbihkJG5yaXNrIC0gZCRuZXZlbnQgLSBkJG5jZW5zb3IsIG5hLnJtID0gDQogIFRSVUUpKSkpOyAudG1wMiR4IDwtIDcgKiBpOyAudG1wMiRGcmVxW2lzLm5hKC50bXAyJEZyZXEpXSA8LSAudG1wMSRGcmVxW2lzLm5hKC50bXAyJEZyZXEpXTsgLnRtcDEgPC0gDQogIC50bXAyOyAubnJpc2sgPC0gcmJpbmQoLm5yaXNrLCAudG1wMil9DQoubnJpc2skeSA8LSByZXAoc2VxKDAuMDI1LCAwLjAyNSwgLTAuMDUpLCA0KQ0KLnBsb3QgPC0gZ2dwbG90KGRhdGEgPSAuZml0LCBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvdXIgPSB6KSkgKyANCiAgZ2VvbV9zdGVwKGRhdGEgPSBzdWJzZXQoLmZpdCwgIWlzLm5hKHVwcGVyKSksIGFlcyh5ID0gdXBwZXIpLCBzaXplID0gMSwgbHR5ID0gMiwgYWxwaGEgPSAwLjUsIA0KICBzaG93LmxlZ2VuZCA9IEZBTFNFLCBuYS5ybSA9IEZBTFNFKSArIA0KICBnZW9tX3N0ZXAoZGF0YSA9IHN1YnNldCguZml0LCAhaXMubmEobG93ZXIpKSwgYWVzKHkgPSBsb3dlciksIHNpemUgPSAxLCBsdHkgPSAyLCBhbHBoYSA9IDAuNSwgDQogIHNob3cubGVnZW5kID0gRkFMU0UsIG5hLnJtID0gRkFMU0UpICsgDQogIGdlb21fc3RlcChzaXplID0gMS41KSArIA0KICBnZW9tX2xpbmVyYW5nZShkYXRhID0gLmNlbnMsIGFlcyh4ID0geCwgeW1pbiA9IHksIHltYXggPSB5ICsgMC4wMiksIHNpemUgPSAxLjUpICsgDQogIGdlb21fdmxpbmUoZGF0YSA9IC5tZWQsIGFlcyh4aW50ZXJjZXB0ID0gbWVkaWFuKSwgY29sb3VyID0gImJsYWNrIiwgbHR5ID0gMikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpLCBleHBhbmQgPSBjKDAuMDEsIDApKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHhsYWIoIlRlbXBvIGVtIGFub3MgZGUgYWJvbm8iKSArIA0KICB5bGFiKCJQcm9iYWJpbGlkYWRlIFModCkiKSArIA0KICBsYWJzKHRpdGxlID0gIkVzdGltYWRvciBkZSBLYXBsYW4tTWVpZXIiKSArIA0KICB0aGVtZV9ncmV5KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2ZhbWlseSA9ICJzYW5zIikgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KLm5yaXNrJHkgPC0gMC41DQoucGxvdDIgPC0gZ2dwbG90KGRhdGEgPSAubnJpc2ssIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0gRnJlcSwgY29sb3VyID0geikpICsgDQogIGdlb21fdGV4dChzaXplID0gMTQgKiAwLjI4MiwgZmFtaWx5ID0gInNhbnMiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDIxLCBieSA9IDcpLCBsaW1pdHMgPSBjKDAsIDIxKSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsgDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKyANCiAgeWxhYigiVGVtcG8gZW0gYW5vcyBkZSBhYm9ubyIpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlzayh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KLnBsb3QzIDwtIGdncGxvdChkYXRhID0gc3Vic2V0KC5ucmlzaywgeCA9PSAwKSwgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSB6LCBjb2xvdXIgPSB6KSkgKyANCiAgZ2VvbV90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsIDUpKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKyANCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArIA0KICBSY21kclBsdWdpbi5LTWdncGxvdDI6OnRoZW1lX25hdHJpc2syMSh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KLnBsb3RiIDwtIGdncGxvdCguZGYsIGFlcyh4ID0geCwgeSA9IHkpKSArIA0KICBnZW9tX2JsYW5rKCkgKyANCiAgUmNtZHJQbHVnaW4uS01nZ3Bsb3QyOjp0aGVtZV9uYXRyaXNrYmcodGhlbWVfZ3JleSwgMTQsICJzYW5zIikNCmdyaWQ6OmdyaWQubmV3cGFnZSgpOyBncmlkOjpwdXNoVmlld3BvcnQoZ3JpZDo6dmlld3BvcnQobGF5b3V0ID0gZ3JpZDo6Z3JpZC5sYXlvdXQoMiwgMiwgaGVpZ2h0cyA9IA0KICB1bml0KGMoMSwgMi41KSwgYygibnVsbCIsICJsaW5lcyIpKSwgd2lkdGhzICA9IHVuaXQoYyg0LCAxKSwgYygibGluZXMiLCAibnVsbCIpKSkpKTsgcHJpbnQoLnBsb3RiLCB2cCA9IA0KICBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDE6MiwgbGF5b3V0LnBvcy5jb2wgPSAxOjIpKTsgcHJpbnQoLnBsb3QgLCB2cCA9IA0KICBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDEgICwgbGF5b3V0LnBvcy5jb2wgPSAxOjIpKTsgcHJpbnQoLnBsb3QyLCB2cCA9IA0KICBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDIgICwgbGF5b3V0LnBvcy5jb2wgPSAxOjIpKTsgcHJpbnQoLnBsb3QzLCB2cCA9IA0KICBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDIgICwgbGF5b3V0LnBvcy5jb2wgPSAxICApKTsgLnBsb3QgPC0gcmVjb3JkUGxvdCgpDQpwcmludCgucGxvdCkNCnJtKC5kZiwgLmZpdCwgLnBtZWQsIC5tZWQsIC5jZW5zLCAudG1wMSwgLnRtcDIsIC5ucmlzaywgLnBsb3QsIC5wbG90MiwgLnBsb3QzLCAucGxvdGIpDQpgYGANCg0KDQpgYGB7cn0NCnJlcXVpcmUoImdncGxvdDIiKQ0KLmRmIDwtIG5hLm9taXQoZGF0YS5mcmFtZSh4ID0gbWVzMDYxOSR0ZW1wbywgeSA9IG1lczA2MTkkc3RhdHVzLCB6ID0gDQogIG1lczA2MTkkU0VYTykpDQouZGYgPC0gLmRmW2RvLmNhbGwob3JkZXIsIC5kZlssIGMoInoiLCAieCIpLCBkcm9wID0gRkFMU0VdKSwgLCBkcm9wID0gRkFMU0VdDQouZml0IDwtIHN1cnZpdmFsOjpzdXJ2Zml0KHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSANCiAgInJpZ2h0IikgfiB6LCAuZGYpDQoucHZhbCA8LSBwbHlyOjpkZHBseSguZGYsIHBseXI6Oi4oKSwNCiBmdW5jdGlvbih4KSB7DQogIGRhdGEuZnJhbWUoDQogICB4ID0gMCwgeSA9IDAsIGRmID0gMSwNCiAgIGNoaXNxID0gc3Vydml2YWw6OnN1cnZkaWZmKA0KICAgIHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSAicmlnaHQiKSB+IHosIHgNCiAgICkkY2hpc3ENCil9KQ0KLnB2YWwkbGFiZWwgPC0gcGFzdGUwKA0KICAicGFzdGUoaXRhbGljKHApLCBcIiA9ICIsDQogIHNpZ25pZigxIC0gcGNoaXNxKC5wdmFsJGNoaXNxLCAucHZhbCRkZiksIDMpLA0KICAiXCIpIg0KKQ0KLmZpdCA8LSBkYXRhLmZyYW1lKHggPSAuZml0JHRpbWUsIHkgPSAuZml0JHN1cnYsIG5yaXNrID0gLmZpdCRuLnJpc2ssIA0KICBuZXZlbnQgPSAuZml0JG4uZXZlbnQsIG5jZW5zb3I9IC5maXQkbi5jZW5zb3IsIHVwcGVyID0gLmZpdCR1cHBlciwgbG93ZXIgPSANCiAgLmZpdCRsb3dlcikNCi5kZiA8LSAuZGZbIWR1cGxpY2F0ZWQoLmRmWyxjKCJ4IiwgInoiKV0pLCBdDQouZGYgPC0gLmZpdCA8LSBkYXRhLmZyYW1lKC5maXQsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSkNCi5kZiA8LSAuZml0IDwtIHJiaW5kKHVuaXF1ZShkYXRhLmZyYW1lKHggPSAwLCB5ID0gMSwgbnJpc2sgPSBOQSwgbmV2ZW50ID0gDQogIE5BLCBuY2Vuc29yID0gTkEsIHVwcGVyID0gMSwgbG93ZXIgPSAxLCAuZGZbLCBjKCJ6IiksIGRyb3AgPSBGQUxTRV0pKSwgLmZpdCkNCi5jZW5zIDwtIHN1YnNldCguZml0LCBuY2Vuc29yID09IDEpDQoudG1wMSA8LSBkYXRhLmZyYW1lKGFzLnRhYmxlKGJ5KC5kZiwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdLCANCiAgZnVuY3Rpb24oZCkgbWF4KGQkbnJpc2ssIG5hLnJtID0gVFJVRSkpKSkNCi50bXAxJHggPC0gMA0KLm5yaXNrIDwtIC50bXAxDQpmb3IgKGkgaW4gMTozKSB7LmRmIDwtIHN1YnNldCguZml0LCB4IDwgNyAqIGkpOyAudG1wMiA8LSANCiAgZGF0YS5mcmFtZShhcy50YWJsZShieSguZGYsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSwgZnVuY3Rpb24oZCkgaWYgDQogIChhbGwoaXMubmEoZCRucmlzaykpKSBOQSBlbHNlIG1pbihkJG5yaXNrIC0gZCRuZXZlbnQgLSBkJG5jZW5zb3IsIG5hLnJtID0gDQogIFRSVUUpKSkpOyAudG1wMiR4IDwtIDcgKiBpOyAudG1wMiRGcmVxW2lzLm5hKC50bXAyJEZyZXEpXSA8LSANCiAgLnRtcDEkRnJlcVtpcy5uYSgudG1wMiRGcmVxKV07IC50bXAxIDwtIC50bXAyOyAubnJpc2sgPC0gcmJpbmQoLm5yaXNrLCANCiAgLnRtcDIpfQ0KLm5yaXNrJHkgPC0gcmVwKHNlcSgwLjA3NSwgMC4wMjUsIC0wLjA1KSwgNCkNCi5wbG90IDwtIGdncGxvdChkYXRhID0gLmZpdCwgYWVzKHggPSB4LCB5ID0geSwgY29sb3VyID0geikpICsgDQogIGdlb21fc3RlcChkYXRhID0gc3Vic2V0KC5maXQsICFpcy5uYSh1cHBlcikpLCBhZXMoeSA9IHVwcGVyKSwgc2l6ZSA9IDEsIA0KICBsdHkgPSAyLCBhbHBoYSA9IDAuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgbmEucm0gPSBGQUxTRSkgKyANCiAgZ2VvbV9zdGVwKGRhdGEgPSBzdWJzZXQoLmZpdCwgIWlzLm5hKGxvd2VyKSksIGFlcyh5ID0gbG93ZXIpLCBzaXplID0gMSwgDQogIGx0eSA9IDIsIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBuYS5ybSA9IEZBTFNFKSArIA0KICBnZW9tX3N0ZXAoc2l6ZSA9IDEuNSkgKyANCiAgZ2VvbV9saW5lcmFuZ2UoZGF0YSA9IC5jZW5zLCBhZXMoeCA9IHgsIHltaW4gPSB5LCB5bWF4ID0geSArIDAuMDIpLCBzaXplIA0KICA9IDEuNSkgKyANCiAgZ2VvbV90ZXh0KGRhdGEgPSAucHZhbCwgYWVzKHkgPSB5LCB4ID0geCwgbGFiZWwgPSBsYWJlbCksIGNvbG91ciA9IA0KICAiYmxhY2siLCBoanVzdCA9IDAsIHZqdXN0ID0gLTAuNSwgcGFyc2UgPSBUUlVFLCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBzaXplID0gDQogIDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpLCBleHBhbmQgPSBjKDAuMDEsIDApKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHhsYWIoIlRlbXBvIGVtIGFub3MgZGUgYWJvbm8iKSArIA0KICB5bGFiKCJQcm9iYWJpZGFkZSBTKHQpIikgKyANCiAgbGFicyhjb2xvdXIgPSAiU0VYTyIpICsgDQogIGxhYnModGl0bGUgPSAiRXN0aW1hZG9yIGRlIEthcGxhbi1NZWllciIpICsgDQogIHRoZW1lX2dyZXkoYmFzZV9zaXplID0gMTQsIGJhc2VfZmFtaWx5ID0gInNhbnMiKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIA0KICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IikpDQoubnJpc2skeSA8LSAoKC5ucmlzayR5IC0gMC4wMjUpIC8gKG1heCgubnJpc2skeSkgLSAwLjAyNSkgKyAwLjUpICogMC41DQoucGxvdDIgPC0gZ2dwbG90KGRhdGEgPSAubnJpc2ssIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0gRnJlcSwgY29sb3VyID0gDQogIHopKSArIA0KICBnZW9tX3RleHQoc2l6ZSA9IDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHlsYWIoIlByb2JhYmlkYWRlIFModCkiKSArIA0KICBSY21kclBsdWdpbi5LTWdncGxvdDI6OnRoZW1lX25hdHJpc2sodGhlbWVfZ3JleSwgMTQsICJzYW5zIikNCi5wbG90MyA8LSBnZ3Bsb3QoZGF0YSA9IHN1YnNldCgubnJpc2ssIHggPT0gMCksIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0geiwNCiAgIGNvbG91ciA9IHopKSArIA0KICBnZW9tX3RleHQoaGp1c3QgPSAwLCBzaXplID0gMTQgKiAwLjI4MiwgZmFtaWx5ID0gInNhbnMiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwgNSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlzazIxKHRoZW1lX2dyZXksIDE0LCAic2FucyIpDQoucGxvdGIgPC0gZ2dwbG90KC5kZiwgYWVzKHggPSB4LCB5ID0geSkpICsgDQogIGdlb21fYmxhbmsoKSArIA0KICBSY21kclBsdWdpbi5LTWdncGxvdDI6OnRoZW1lX25hdHJpc2tiZyh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KZ3JpZDo6Z3JpZC5uZXdwYWdlKCk7IGdyaWQ6OnB1c2hWaWV3cG9ydChncmlkOjp2aWV3cG9ydChsYXlvdXQgPSANCiAgZ3JpZDo6Z3JpZC5sYXlvdXQoMiwgMiwgaGVpZ2h0cyA9IHVuaXQoYygxLCAzKSwgYygibnVsbCIsICJsaW5lcyIpKSwgd2lkdGhzIA0KICAgPSB1bml0KGMoNCwgMSksIGMoImxpbmVzIiwgIm51bGwiKSkpKSk7IHByaW50KC5wbG90YiwgdnAgPSANCiAgZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxOjIsIGxheW91dC5wb3MuY29sID0gMToyKSk7IHByaW50KC5wbG90ICwgDQogIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxICAsIGxheW91dC5wb3MuY29sID0gMToyKSk7IA0KICBwcmludCgucGxvdDIsIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyICAsIGxheW91dC5wb3MuY29sID0gDQogIDE6MikpOyBwcmludCgucGxvdDMsIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyICAsIA0KICBsYXlvdXQucG9zLmNvbCA9IDEgICkpOyAucGxvdCA8LSByZWNvcmRQbG90KCkNCnByaW50KC5wbG90KQ0Kcm0oLmRmLCAuZml0LCAucHZhbCwgLnBwdmFsLCAuY2VucywgLnRtcDEsIC50bXAyLCAubnJpc2ssIC5wbG90LCAucGxvdDIsIA0KICAucGxvdDMsIC5wbG90YikNCmBgYA0KDQoNCmBgYHtyfQ0KLlN1cnZmaXQgPC0gc3VydmZpdChTdXJ2KHRlbXBvLCBzdGF0dXMsIHR5cGU9InJpZ2h0IikgfiBTRVhPLCANCiAgY29uZi50eXBlPSJsb2ciLCBjb25mLmludD0wLjk1LCB0eXBlPSJrYXBsYW4tbWVpZXIiLCBlcnJvcj0iZ3JlZW53b29kIiwgDQogIGRhdGE9bWVzMDYxOSkNCi5TdXJ2Zml0DQoNCnF1YW50aWxlKC5TdXJ2Zml0LCBxdWFudGlsZXM9YyguMjUsLjUsLjc1KSkNCnJlbW92ZSguU3VydmZpdCkNCg0KYGBgDQoNCmBgYHtyfQ0KDQpyZXF1aXJlKCJnZ3Bsb3QyIikNCi5kZiA8LSBuYS5vbWl0KGRhdGEuZnJhbWUoeCA9IG1lczA2MTkkdGVtcG8sIHkgPSBtZXMwNjE5JHN0YXR1cywgeiA9IA0KICBtZXMwNjE5JGlkX2luaV9zZXJ2X3B1YikpDQouZGYgPC0gLmRmW2RvLmNhbGwob3JkZXIsIC5kZlssIGMoInoiLCAieCIpLCBkcm9wID0gRkFMU0VdKSwgLCBkcm9wID0gRkFMU0VdDQouZml0IDwtIHN1cnZpdmFsOjpzdXJ2Zml0KHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSANCiAgInJpZ2h0IikgfiB6LCAuZGYpDQoucHZhbCA8LSBwbHlyOjpkZHBseSguZGYsIHBseXI6Oi4oKSwNCiBmdW5jdGlvbih4KSB7DQogIGRhdGEuZnJhbWUoDQogICB4ID0gMCwgeSA9IDAsIGRmID0gMywNCiAgIGNoaXNxID0gc3Vydml2YWw6OnN1cnZkaWZmKA0KICAgIHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSAicmlnaHQiKSB+IHosIHgNCiAgICkkY2hpc3ENCil9KQ0KLnB2YWwkbGFiZWwgPC0gcGFzdGUwKA0KICAicGFzdGUoaXRhbGljKHApLCBcIiA9ICIsDQogIHNpZ25pZigxIC0gcGNoaXNxKC5wdmFsJGNoaXNxLCAucHZhbCRkZiksIDMpLA0KICAiXCIpIg0KKQ0KLmZpdCA8LSBkYXRhLmZyYW1lKHggPSAuZml0JHRpbWUsIHkgPSAuZml0JHN1cnYsIG5yaXNrID0gLmZpdCRuLnJpc2ssIA0KICBuZXZlbnQgPSAuZml0JG4uZXZlbnQsIG5jZW5zb3I9IC5maXQkbi5jZW5zb3IsIHVwcGVyID0gLmZpdCR1cHBlciwgbG93ZXIgPSANCiAgLmZpdCRsb3dlcikNCi5kZiA8LSAuZGZbIWR1cGxpY2F0ZWQoLmRmWyxjKCJ4IiwgInoiKV0pLCBdDQouZGYgPC0gLmZpdCA8LSBkYXRhLmZyYW1lKC5maXQsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSkNCi5kZiA8LSAuZml0IDwtIHJiaW5kKHVuaXF1ZShkYXRhLmZyYW1lKHggPSAwLCB5ID0gMSwgbnJpc2sgPSBOQSwgbmV2ZW50ID0gDQogIE5BLCBuY2Vuc29yID0gTkEsIHVwcGVyID0gMSwgbG93ZXIgPSAxLCAuZGZbLCBjKCJ6IiksIGRyb3AgPSBGQUxTRV0pKSwgLmZpdCkNCi5jZW5zIDwtIHN1YnNldCguZml0LCBuY2Vuc29yID09IDEpDQoudG1wMSA8LSBkYXRhLmZyYW1lKGFzLnRhYmxlKGJ5KC5kZiwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdLCANCiAgZnVuY3Rpb24oZCkgbWF4KGQkbnJpc2ssIG5hLnJtID0gVFJVRSkpKSkNCi50bXAxJHggPC0gMA0KLm5yaXNrIDwtIC50bXAxDQpmb3IgKGkgaW4gMTozKSB7LmRmIDwtIHN1YnNldCguZml0LCB4IDwgNyAqIGkpOyAudG1wMiA8LSANCiAgZGF0YS5mcmFtZShhcy50YWJsZShieSguZGYsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSwgZnVuY3Rpb24oZCkgaWYgDQogIChhbGwoaXMubmEoZCRucmlzaykpKSBOQSBlbHNlIG1pbihkJG5yaXNrIC0gZCRuZXZlbnQgLSBkJG5jZW5zb3IsIG5hLnJtID0gDQogIFRSVUUpKSkpOyAudG1wMiR4IDwtIDcgKiBpOyAudG1wMiRGcmVxW2lzLm5hKC50bXAyJEZyZXEpXSA8LSANCiAgLnRtcDEkRnJlcVtpcy5uYSgudG1wMiRGcmVxKV07IC50bXAxIDwtIC50bXAyOyAubnJpc2sgPC0gcmJpbmQoLm5yaXNrLCANCiAgLnRtcDIpfQ0KLm5yaXNrJHkgPC0gcmVwKHNlcSgwLjE3NSwgMC4wMjUsIC0wLjA1KSwgNCkNCi5wbG90IDwtIGdncGxvdChkYXRhID0gLmZpdCwgYWVzKHggPSB4LCB5ID0geSwgY29sb3VyID0geikpICsgDQogIGdlb21fc3RlcChkYXRhID0gc3Vic2V0KC5maXQsICFpcy5uYSh1cHBlcikpLCBhZXMoeSA9IHVwcGVyKSwgc2l6ZSA9IDEsIA0KICBsdHkgPSAyLCBhbHBoYSA9IDAuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgbmEucm0gPSBGQUxTRSkgKyANCiAgZ2VvbV9zdGVwKGRhdGEgPSBzdWJzZXQoLmZpdCwgIWlzLm5hKGxvd2VyKSksIGFlcyh5ID0gbG93ZXIpLCBzaXplID0gMSwgDQogIGx0eSA9IDIsIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBuYS5ybSA9IEZBTFNFKSArIA0KICBnZW9tX3N0ZXAoc2l6ZSA9IDEuNSkgKyANCiAgZ2VvbV9saW5lcmFuZ2UoZGF0YSA9IC5jZW5zLCBhZXMoeCA9IHgsIHltaW4gPSB5LCB5bWF4ID0geSArIDAuMDIpLCBzaXplIA0KICA9IDEuNSkgKyANCiAgZ2VvbV90ZXh0KGRhdGEgPSAucHZhbCwgYWVzKHkgPSB5LCB4ID0geCwgbGFiZWwgPSBsYWJlbCksIGNvbG91ciA9IA0KICAiYmxhY2siLCBoanVzdCA9IDAsIHZqdXN0ID0gLTAuNSwgcGFyc2UgPSBUUlVFLCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBzaXplID0gDQogIDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpLCBleHBhbmQgPSBjKDAuMDEsIDApKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHhsYWIoIlRlbXBvIGVtIGFub3MgZGUgYWJvbm8iKSArIA0KICB5bGFiKCJQcm9iYWJpbGlkYWRlIGRlIFModCkiKSArIA0KICBsYWJzKGNvbG91ciA9ICJpZF9pbmlfc2Vydl9wdWIiKSArIA0KICBsYWJzKHRpdGxlID0gIkVzdGltYWRvciBkZSBLYXBsYW4tTWVpZXIiKSArIA0KICB0aGVtZV9ncmV5KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2ZhbWlseSA9ICJzYW5zIikgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygxLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCANCiAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpKQ0KLm5yaXNrJHkgPC0gKCgubnJpc2skeSAtIDAuMDI1KSAvIChtYXgoLm5yaXNrJHkpIC0gMC4wMjUpICsgMC4xMjUpICogMC44DQoucGxvdDIgPC0gZ2dwbG90KGRhdGEgPSAubnJpc2ssIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0gRnJlcSwgY29sb3VyID0gDQogIHopKSArIA0KICBnZW9tX3RleHQoc2l6ZSA9IDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHlsYWIoIlByb2JhYmlsaWRhZGUgZGUgUyh0KSIpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlzayh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KLnBsb3QzIDwtIGdncGxvdChkYXRhID0gc3Vic2V0KC5ucmlzaywgeCA9PSAwKSwgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSB6LA0KICAgY29sb3VyID0geikpICsgDQogIGdlb21fdGV4dChoanVzdCA9IDAsIHNpemUgPSAxNCAqIDAuMjgyLCBmYW1pbHkgPSAic2FucyIpICsgDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LCA1KSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsgDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKyANCiAgUmNtZHJQbHVnaW4uS01nZ3Bsb3QyOjp0aGVtZV9uYXRyaXNrMjEodGhlbWVfZ3JleSwgMTQsICJzYW5zIikNCi5wbG90YiA8LSBnZ3Bsb3QoLmRmLCBhZXMoeCA9IHgsIHkgPSB5KSkgKyANCiAgZ2VvbV9ibGFuaygpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlza2JnKHRoZW1lX2dyZXksIDE0LCAic2FucyIpDQpncmlkOjpncmlkLm5ld3BhZ2UoKTsgZ3JpZDo6cHVzaFZpZXdwb3J0KGdyaWQ6OnZpZXdwb3J0KGxheW91dCA9IA0KICBncmlkOjpncmlkLmxheW91dCgyLCAyLCBoZWlnaHRzID0gdW5pdChjKDEsIDQpLCBjKCJudWxsIiwgImxpbmVzIikpLCB3aWR0aHMgDQogICA9IHVuaXQoYyg0LCAxKSwgYygibGluZXMiLCAibnVsbCIpKSkpKTsgcHJpbnQoLnBsb3RiLCB2cCA9IA0KICBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDE6MiwgbGF5b3V0LnBvcy5jb2wgPSAxOjIpKTsgcHJpbnQoLnBsb3QgLCANCiAgdnAgPSBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDEgICwgbGF5b3V0LnBvcy5jb2wgPSAxOjIpKTsgDQogIHByaW50KC5wbG90MiwgdnAgPSBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDIgICwgbGF5b3V0LnBvcy5jb2wgPSANCiAgMToyKSk7IHByaW50KC5wbG90MywgdnAgPSBncmlkOjp2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDIgICwgDQogIGxheW91dC5wb3MuY29sID0gMSAgKSk7IC5wbG90IDwtIHJlY29yZFBsb3QoKQ0KcHJpbnQoLnBsb3QpDQpybSguZGYsIC5maXQsIC5wdmFsLCAucHB2YWwsIC5jZW5zLCAudG1wMSwgLnRtcDIsIC5ucmlzaywgLnBsb3QsIC5wbG90MiwgDQogIC5wbG90MywgLnBsb3RiKQ0KYGBgDQoNCmBgYHtyfQ0KLlN1cnZmaXQgPC0gc3VydmZpdChTdXJ2KHRlbXBvLCBzdGF0dXMsIHR5cGU9InJpZ2h0IikgfiBpZF9pbmlfc2Vydl9wdWIsIA0KICBjb25mLnR5cGU9ImxvZyIsIGNvbmYuaW50PTAuOTUsIHR5cGU9ImthcGxhbi1tZWllciIsIGVycm9yPSJncmVlbndvb2QiLCANCiAgZGF0YT1tZXMwNjE5KQ0KLlN1cnZmaXQNCg0KcXVhbnRpbGUoLlN1cnZmaXQsIHF1YW50aWxlcz1jKC4yNSwuNSwuNzUpKSANCnJlbW92ZSguU3VydmZpdCkNCg0KYGBgDQoNCmBgYHtyfQ0KcmVxdWlyZSgiZ2dwbG90MiIpDQouZGYgPC0gbmEub21pdChkYXRhLmZyYW1lKHggPSBtZXMwNjE5JHRlbXBvLCB5ID0gbWVzMDYxOSRzdGF0dXMsIHogPSANCiAgbWVzMDYxOSRUaXBvX1JlZ2lhbykpDQouZGYgPC0gLmRmW2RvLmNhbGwob3JkZXIsIC5kZlssIGMoInoiLCAieCIpLCBkcm9wID0gRkFMU0VdKSwgLCBkcm9wID0gRkFMU0VdDQouZml0IDwtIHN1cnZpdmFsOjpzdXJ2Zml0KHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSANCiAgInJpZ2h0IikgfiB6LCAuZGYpDQoucHZhbCA8LSBwbHlyOjpkZHBseSguZGYsIHBseXI6Oi4oKSwNCiBmdW5jdGlvbih4KSB7DQogIGRhdGEuZnJhbWUoDQogICB4ID0gMCwgeSA9IDAsIGRmID0gMiwNCiAgIGNoaXNxID0gc3Vydml2YWw6OnN1cnZkaWZmKA0KICAgIHN1cnZpdmFsOjpTdXJ2KHRpbWUgPSB4LCBldmVudCA9IHksIHR5cGUgPSAicmlnaHQiKSB+IHosIHgNCiAgICkkY2hpc3ENCil9KQ0KLnB2YWwkbGFiZWwgPC0gcGFzdGUwKA0KICAicGFzdGUoaXRhbGljKHApLCBcIiA9ICIsDQogIHNpZ25pZigxIC0gcGNoaXNxKC5wdmFsJGNoaXNxLCAucHZhbCRkZiksIDMpLA0KICAiXCIpIg0KKQ0KLmZpdCA8LSBkYXRhLmZyYW1lKHggPSAuZml0JHRpbWUsIHkgPSAuZml0JHN1cnYsIG5yaXNrID0gLmZpdCRuLnJpc2ssIA0KICBuZXZlbnQgPSAuZml0JG4uZXZlbnQsIG5jZW5zb3I9IC5maXQkbi5jZW5zb3IsIHVwcGVyID0gLmZpdCR1cHBlciwgbG93ZXIgPSANCiAgLmZpdCRsb3dlcikNCi5kZiA8LSAuZGZbIWR1cGxpY2F0ZWQoLmRmWyxjKCJ4IiwgInoiKV0pLCBdDQouZGYgPC0gLmZpdCA8LSBkYXRhLmZyYW1lKC5maXQsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSkNCi5kZiA8LSAuZml0IDwtIHJiaW5kKHVuaXF1ZShkYXRhLmZyYW1lKHggPSAwLCB5ID0gMSwgbnJpc2sgPSBOQSwgbmV2ZW50ID0gDQogIE5BLCBuY2Vuc29yID0gTkEsIHVwcGVyID0gMSwgbG93ZXIgPSAxLCAuZGZbLCBjKCJ6IiksIGRyb3AgPSBGQUxTRV0pKSwgLmZpdCkNCi5jZW5zIDwtIHN1YnNldCguZml0LCBuY2Vuc29yID09IDEpDQoudG1wMSA8LSBkYXRhLmZyYW1lKGFzLnRhYmxlKGJ5KC5kZiwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdLCANCiAgZnVuY3Rpb24oZCkgbWF4KGQkbnJpc2ssIG5hLnJtID0gVFJVRSkpKSkNCi50bXAxJHggPC0gMA0KLm5yaXNrIDwtIC50bXAxDQpmb3IgKGkgaW4gMTozKSB7LmRmIDwtIHN1YnNldCguZml0LCB4IDwgNyAqIGkpOyAudG1wMiA8LSANCiAgZGF0YS5mcmFtZShhcy50YWJsZShieSguZGYsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSwgZnVuY3Rpb24oZCkgaWYgDQogIChhbGwoaXMubmEoZCRucmlzaykpKSBOQSBlbHNlIG1pbihkJG5yaXNrIC0gZCRuZXZlbnQgLSBkJG5jZW5zb3IsIG5hLnJtID0gDQogIFRSVUUpKSkpOyAudG1wMiR4IDwtIDcgKiBpOyAudG1wMiRGcmVxW2lzLm5hKC50bXAyJEZyZXEpXSA8LSANCiAgLnRtcDEkRnJlcVtpcy5uYSgudG1wMiRGcmVxKV07IC50bXAxIDwtIC50bXAyOyAubnJpc2sgPC0gcmJpbmQoLm5yaXNrLCANCiAgLnRtcDIpfQ0KLm5yaXNrJHkgPC0gcmVwKHNlcSgwLjEyNSwgMC4wMjUsIC0wLjA1KSwgNCkNCi5wbG90IDwtIGdncGxvdChkYXRhID0gLmZpdCwgYWVzKHggPSB4LCB5ID0geSwgY29sb3VyID0geikpICsgDQogIGdlb21fc3RlcChkYXRhID0gc3Vic2V0KC5maXQsICFpcy5uYSh1cHBlcikpLCBhZXMoeSA9IHVwcGVyKSwgc2l6ZSA9IDEsIA0KICBsdHkgPSAyLCBhbHBoYSA9IDAuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgbmEucm0gPSBGQUxTRSkgKyANCiAgZ2VvbV9zdGVwKGRhdGEgPSBzdWJzZXQoLmZpdCwgIWlzLm5hKGxvd2VyKSksIGFlcyh5ID0gbG93ZXIpLCBzaXplID0gMSwgDQogIGx0eSA9IDIsIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBuYS5ybSA9IEZBTFNFKSArIA0KICBnZW9tX3N0ZXAoc2l6ZSA9IDEuNSkgKyANCiAgZ2VvbV9saW5lcmFuZ2UoZGF0YSA9IC5jZW5zLCBhZXMoeCA9IHgsIHltaW4gPSB5LCB5bWF4ID0geSArIDAuMDIpLCBzaXplIA0KICA9IDEuNSkgKyANCiAgZ2VvbV90ZXh0KGRhdGEgPSAucHZhbCwgYWVzKHkgPSB5LCB4ID0geCwgbGFiZWwgPSBsYWJlbCksIGNvbG91ciA9IA0KICAiYmxhY2siLCBoanVzdCA9IDAsIHZqdXN0ID0gLTAuNSwgcGFyc2UgPSBUUlVFLCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBzaXplID0gDQogIDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpLCBleHBhbmQgPSBjKDAuMDEsIDApKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHhsYWIoIlRlbXBvIGVtIGFub3MgZGUgYWJvbm8iKSArIA0KICB5bGFiKCJQcm9wYWJpbGlkYWRlIGRlIFModCkiKSArIA0KICBsYWJzKGNvbG91ciA9ICJUaXBvX1JlZ2lhbyIpICsgDQogIGxhYnModGl0bGUgPSAiRXN0aW1hZG9yIGRlIEthcGxhbi1NZWllciIpICsgDQogIHRoZW1lX2dyZXkoYmFzZV9zaXplID0gMTQsIGJhc2VfZmFtaWx5ID0gInNhbnMiKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIA0KICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IikpDQoubnJpc2skeSA8LSAoKC5ucmlzayR5IC0gMC4wMjUpIC8gKG1heCgubnJpc2skeSkgLSAwLjAyNSkgKyAwLjEyNSkgKiAwLjgNCi5wbG90MiA8LSBnZ3Bsb3QoZGF0YSA9IC5ucmlzaywgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSBGcmVxLCBjb2xvdXIgPSANCiAgeikpICsgDQogIGdlb21fdGV4dChzaXplID0gMTQgKiAwLjI4MiwgZmFtaWx5ID0gInNhbnMiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDIxLCBieSA9IDcpLCBsaW1pdHMgPSBjKDAsIDIxKSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsgDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKyANCiAgeWxhYigiUHJvcGFiaWxpZGFkZSBkZSBTKHQpIikgKyANCiAgUmNtZHJQbHVnaW4uS01nZ3Bsb3QyOjp0aGVtZV9uYXRyaXNrKHRoZW1lX2dyZXksIDE0LCAic2FucyIpDQoucGxvdDMgPC0gZ2dwbG90KGRhdGEgPSBzdWJzZXQoLm5yaXNrLCB4ID09IDApLCBhZXMoeCA9IHgsIHkgPSB5LCBsYWJlbCA9IHosDQogICBjb2xvdXIgPSB6KSkgKyANCiAgZ2VvbV90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsIDUpKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKyANCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArIA0KICBSY21kclBsdWdpbi5LTWdncGxvdDI6OnRoZW1lX25hdHJpc2syMSh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KLnBsb3RiIDwtIGdncGxvdCguZGYsIGFlcyh4ID0geCwgeSA9IHkpKSArIA0KICBnZW9tX2JsYW5rKCkgKyANCiAgUmNtZHJQbHVnaW4uS01nZ3Bsb3QyOjp0aGVtZV9uYXRyaXNrYmcodGhlbWVfZ3JleSwgMTQsICJzYW5zIikNCmdyaWQ6OmdyaWQubmV3cGFnZSgpOyBncmlkOjpwdXNoVmlld3BvcnQoZ3JpZDo6dmlld3BvcnQobGF5b3V0ID0gDQogIGdyaWQ6OmdyaWQubGF5b3V0KDIsIDIsIGhlaWdodHMgPSB1bml0KGMoMSwgMy41KSwgYygibnVsbCIsICJsaW5lcyIpKSwgDQogIHdpZHRocyAgPSB1bml0KGMoNCwgMSksIGMoImxpbmVzIiwgIm51bGwiKSkpKSk7IHByaW50KC5wbG90YiwgdnAgPSANCiAgZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxOjIsIGxheW91dC5wb3MuY29sID0gMToyKSk7IHByaW50KC5wbG90ICwgDQogIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxICAsIGxheW91dC5wb3MuY29sID0gMToyKSk7IA0KICBwcmludCgucGxvdDIsIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyICAsIGxheW91dC5wb3MuY29sID0gDQogIDE6MikpOyBwcmludCgucGxvdDMsIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyICAsIA0KICBsYXlvdXQucG9zLmNvbCA9IDEgICkpOyAucGxvdCA8LSByZWNvcmRQbG90KCkNCnByaW50KC5wbG90KQ0Kcm0oLmRmLCAuZml0LCAucHZhbCwgLnBwdmFsLCAuY2VucywgLnRtcDEsIC50bXAyLCAubnJpc2ssIC5wbG90LCAucGxvdDIsIA0KICAucGxvdDMsIC5wbG90YikNCmBgYA0KDQpgYGB7cn0NCi5TdXJ2Zml0IDwtIHN1cnZmaXQoU3Vydih0ZW1wbywgc3RhdHVzLCB0eXBlPSJyaWdodCIpIH4gVGlwb19SZWdpYW8sIA0KICBjb25mLnR5cGU9ImxvZyIsIGNvbmYuaW50PTAuOTUsIHR5cGU9ImthcGxhbi1tZWllciIsIGVycm9yPSJncmVlbndvb2QiLCANCiAgZGF0YT1tZXMwNjE5KQ0KLlN1cnZmaXQNCg0KcXVhbnRpbGUoLlN1cnZmaXQsIHF1YW50aWxlcz1jKC4yNSwuNSwuNzUpKSANCnJlbW92ZSguU3VydmZpdCkNCmBgYA0KDQoNCmBgYHtyfQ0KcmVxdWlyZSgiZ2dwbG90MiIpDQouZGYgPC0gbmEub21pdChkYXRhLmZyYW1lKHggPSBtZXMwNjE5JHRlbXBvLCB5ID0gbWVzMDYxOSRzdGF0dXMsIHogPSANCiAgbWVzMDYxOSREZXNjX1JlbmRhX0JydXRhKSkNCi5kZiA8LSAuZGZbZG8uY2FsbChvcmRlciwgLmRmWywgYygieiIsICJ4IiksIGRyb3AgPSBGQUxTRV0pLCAsIGRyb3AgPSBGQUxTRV0NCi5maXQgPC0gc3Vydml2YWw6OnN1cnZmaXQoc3Vydml2YWw6OlN1cnYodGltZSA9IHgsIGV2ZW50ID0geSwgdHlwZSA9IA0KICAicmlnaHQiKSB+IHosIC5kZikNCi5wdmFsIDwtIHBseXI6OmRkcGx5KC5kZiwgcGx5cjo6LigpLA0KIGZ1bmN0aW9uKHgpIHsNCiAgZGF0YS5mcmFtZSgNCiAgIHggPSAwLCB5ID0gMCwgZGYgPSAzLA0KICAgY2hpc3EgPSBzdXJ2aXZhbDo6c3VydmRpZmYoDQogICAgc3Vydml2YWw6OlN1cnYodGltZSA9IHgsIGV2ZW50ID0geSwgdHlwZSA9ICJyaWdodCIpIH4geiwgeA0KICAgKSRjaGlzcQ0KKX0pDQoucHZhbCRsYWJlbCA8LSBwYXN0ZTAoDQogICJwYXN0ZShpdGFsaWMocCksIFwiID0gIiwNCiAgc2lnbmlmKDEgLSBwY2hpc3EoLnB2YWwkY2hpc3EsIC5wdmFsJGRmKSwgMyksDQogICJcIikiDQopDQouZml0IDwtIGRhdGEuZnJhbWUoeCA9IC5maXQkdGltZSwgeSA9IC5maXQkc3VydiwgbnJpc2sgPSAuZml0JG4ucmlzaywgDQogIG5ldmVudCA9IC5maXQkbi5ldmVudCwgbmNlbnNvcj0gLmZpdCRuLmNlbnNvciwgdXBwZXIgPSAuZml0JHVwcGVyLCBsb3dlciA9IA0KICAuZml0JGxvd2VyKQ0KLmRmIDwtIC5kZlshZHVwbGljYXRlZCguZGZbLGMoIngiLCAieiIpXSksIF0NCi5kZiA8LSAuZml0IDwtIGRhdGEuZnJhbWUoLmZpdCwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdKQ0KLmRmIDwtIC5maXQgPC0gcmJpbmQodW5pcXVlKGRhdGEuZnJhbWUoeCA9IDAsIHkgPSAxLCBucmlzayA9IE5BLCBuZXZlbnQgPSANCiAgTkEsIG5jZW5zb3IgPSBOQSwgdXBwZXIgPSAxLCBsb3dlciA9IDEsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSkpLCAuZml0KQ0KLmNlbnMgPC0gc3Vic2V0KC5maXQsIG5jZW5zb3IgPT0gMSkNCi50bXAxIDwtIGRhdGEuZnJhbWUoYXMudGFibGUoYnkoLmRmLCAuZGZbLCBjKCJ6IiksIGRyb3AgPSBGQUxTRV0sIA0KICBmdW5jdGlvbihkKSBtYXgoZCRucmlzaywgbmEucm0gPSBUUlVFKSkpKQ0KLnRtcDEkeCA8LSAwDQoubnJpc2sgPC0gLnRtcDENCmZvciAoaSBpbiAxOjMpIHsuZGYgPC0gc3Vic2V0KC5maXQsIHggPCA3ICogaSk7IC50bXAyIDwtIA0KICBkYXRhLmZyYW1lKGFzLnRhYmxlKGJ5KC5kZiwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdLCBmdW5jdGlvbihkKSBpZiANCiAgKGFsbChpcy5uYShkJG5yaXNrKSkpIE5BIGVsc2UgbWluKGQkbnJpc2sgLSBkJG5ldmVudCAtIGQkbmNlbnNvciwgbmEucm0gPSANCiAgVFJVRSkpKSk7IC50bXAyJHggPC0gNyAqIGk7IC50bXAyJEZyZXFbaXMubmEoLnRtcDIkRnJlcSldIDwtIA0KICAudG1wMSRGcmVxW2lzLm5hKC50bXAyJEZyZXEpXTsgLnRtcDEgPC0gLnRtcDI7IC5ucmlzayA8LSByYmluZCgubnJpc2ssIA0KICAudG1wMil9DQoubnJpc2skeSA8LSByZXAoc2VxKDAuMTc1LCAwLjAyNSwgLTAuMDUpLCA0KQ0KLnBsb3QgPC0gZ2dwbG90KGRhdGEgPSAuZml0LCBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvdXIgPSB6KSkgKyANCiAgZ2VvbV9zdGVwKGRhdGEgPSBzdWJzZXQoLmZpdCwgIWlzLm5hKHVwcGVyKSksIGFlcyh5ID0gdXBwZXIpLCBzaXplID0gMSwgDQogIGx0eSA9IDIsIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBuYS5ybSA9IEZBTFNFKSArIA0KICBnZW9tX3N0ZXAoZGF0YSA9IHN1YnNldCguZml0LCAhaXMubmEobG93ZXIpKSwgYWVzKHkgPSBsb3dlciksIHNpemUgPSAxLCANCiAgbHR5ID0gMiwgYWxwaGEgPSAwLjUsIHNob3cubGVnZW5kID0gRkFMU0UsIG5hLnJtID0gRkFMU0UpICsgDQogIGdlb21fc3RlcChzaXplID0gMS41KSArIA0KICBnZW9tX2xpbmVyYW5nZShkYXRhID0gLmNlbnMsIGFlcyh4ID0geCwgeW1pbiA9IHksIHltYXggPSB5ICsgMC4wMiksIHNpemUgDQogID0gMS41KSArIA0KICBnZW9tX3RleHQoZGF0YSA9IC5wdmFsLCBhZXMoeSA9IHksIHggPSB4LCBsYWJlbCA9IGxhYmVsKSwgY29sb3VyID0gDQogICJibGFjayIsIGhqdXN0ID0gMCwgdmp1c3QgPSAtMC41LCBwYXJzZSA9IFRSVUUsIHNob3cubGVnZW5kID0gRkFMU0UsIHNpemUgPSANCiAgMTQgKiAwLjI4MiwgZmFtaWx5ID0gInNhbnMiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDIxLCBieSA9IDcpLCBsaW1pdHMgPSBjKDAsIDIxKSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSksIGV4cGFuZCA9IGMoMC4wMSwgMCkpICsgDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKyANCiAgeGxhYigiVGltZSBmcm9tIGVudHJ5IikgKyANCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBzdXJ2aXZhbCIpICsgDQogIGxhYnMoY29sb3VyID0gIkRlc2NfUmVuZGFfQnJ1dGEiKSArIA0KICB0aGVtZV9ncmV5KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2ZhbWlseSA9ICJzYW5zIikgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygxLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCANCiAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpKQ0KLm5yaXNrJHkgPC0gKCgubnJpc2skeSAtIDAuMDI1KSAvIChtYXgoLm5yaXNrJHkpIC0gMC4wMjUpICsgMC4xMjUpICogMC44DQoucGxvdDIgPC0gZ2dwbG90KGRhdGEgPSAubnJpc2ssIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0gRnJlcSwgY29sb3VyID0gDQogIHopKSArIA0KICBnZW9tX3RleHQoc2l6ZSA9IDE0ICogMC4yODIsIGZhbWlseSA9ICJzYW5zIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMSwgYnkgPSA3KSwgbGltaXRzID0gYygwLCAyMSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIHlsYWIoIlByb3BvcnRpb24gb2Ygc3Vydml2YWwiKSArIA0KICBSY21kclBsdWdpbi5LTWdncGxvdDI6OnRoZW1lX25hdHJpc2sodGhlbWVfZ3JleSwgMTQsICJzYW5zIikNCi5wbG90MyA8LSBnZ3Bsb3QoZGF0YSA9IHN1YnNldCgubnJpc2ssIHggPT0gMCksIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0geiwNCiAgIGNvbG91ciA9IHopKSArIA0KICBnZW9tX3RleHQoaGp1c3QgPSAwLCBzaXplID0gMTQgKiAwLjI4MiwgZmFtaWx5ID0gInNhbnMiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwgNSkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArIA0KICBzY2FsZV9jb2xvdXJfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlzazIxKHRoZW1lX2dyZXksIDE0LCAic2FucyIpDQoucGxvdGIgPC0gZ2dwbG90KC5kZiwgYWVzKHggPSB4LCB5ID0geSkpICsgDQogIGdlb21fYmxhbmsoKSArIA0KICBSY21kclBsdWdpbi5LTWdncGxvdDI6OnRoZW1lX25hdHJpc2tiZyh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KZ3JpZDo6Z3JpZC5uZXdwYWdlKCk7IGdyaWQ6OnB1c2hWaWV3cG9ydChncmlkOjp2aWV3cG9ydChsYXlvdXQgPSANCiAgZ3JpZDo6Z3JpZC5sYXlvdXQoMiwgMiwgaGVpZ2h0cyA9IHVuaXQoYygxLCA0KSwgYygibnVsbCIsICJsaW5lcyIpKSwgd2lkdGhzIA0KICAgPSB1bml0KGMoNCwgMSksIGMoImxpbmVzIiwgIm51bGwiKSkpKSk7IHByaW50KC5wbG90YiwgdnAgPSANCiAgZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxOjIsIGxheW91dC5wb3MuY29sID0gMToyKSk7IHByaW50KC5wbG90ICwgDQogIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxICAsIGxheW91dC5wb3MuY29sID0gMToyKSk7IA0KICBwcmludCgucGxvdDIsIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyICAsIGxheW91dC5wb3MuY29sID0gDQogIDE6MikpOyBwcmludCgucGxvdDMsIHZwID0gZ3JpZDo6dmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyICAsIA0KICBsYXlvdXQucG9zLmNvbCA9IDEgICkpOyAucGxvdCA8LSByZWNvcmRQbG90KCkNCnByaW50KC5wbG90KQ0Kcm0oLmRmLCAuZml0LCAucHZhbCwgLnBwdmFsLCAuY2VucywgLnRtcDEsIC50bXAyLCAubnJpc2ssIC5wbG90LCAucGxvdDIsIA0KICAucGxvdDMsIC5wbG90YikNCmBgYA0KDQoNCg0KYGBge3J9DQouU3VydmZpdCA8LSBzdXJ2Zml0KFN1cnYodGVtcG8sIHN0YXR1cywgdHlwZT0icmlnaHQiKSB+IERlc2NfUmVuZGFfQnJ1dGEsIA0KICBjb25mLnR5cGU9ImxvZyIsIGNvbmYuaW50PTAuOTUsIHR5cGU9ImthcGxhbi1tZWllciIsIGVycm9yPSJncmVlbndvb2QiLCANCiAgZGF0YT1tZXMwNjE5KQ0KLlN1cnZmaXQNCg0KcXVhbnRpbGUoLlN1cnZmaXQsIHF1YW50aWxlcz1jKC4yNSwuNSwuNzUpKQ0KcmVtb3ZlKC5TdXJ2Zml0KQ0KYGBgDQoNCg0KYGBge3J9DQpyZXF1aXJlKCJnZ3Bsb3QyIikNCi5kZiA8LSBuYS5vbWl0KGRhdGEuZnJhbWUoeCA9IG1lczA2MTkkdGVtcG8sIHkgPSBtZXMwNjE5JHN0YXR1cywgeiA9IA0KICBtZXMwNjE5JFF0ZGVfZGVwZW5kZW50ZXMpKQ0KLmRmIDwtIC5kZltkby5jYWxsKG9yZGVyLCAuZGZbLCBjKCJ6IiwgIngiKSwgZHJvcCA9IEZBTFNFXSksICwgZHJvcCA9IEZBTFNFXQ0KLmZpdCA8LSBzdXJ2aXZhbDo6c3VydmZpdChzdXJ2aXZhbDo6U3Vydih0aW1lID0geCwgZXZlbnQgPSB5LCB0eXBlID0gDQogICJyaWdodCIpIH4geiwgLmRmKQ0KLnB2YWwgPC0gcGx5cjo6ZGRwbHkoLmRmLCBwbHlyOjouKCksDQogZnVuY3Rpb24oeCkgew0KICBkYXRhLmZyYW1lKA0KICAgeCA9IDAsIHkgPSAwLCBkZiA9IDIsDQogICBjaGlzcSA9IHN1cnZpdmFsOjpzdXJ2ZGlmZigNCiAgICBzdXJ2aXZhbDo6U3Vydih0aW1lID0geCwgZXZlbnQgPSB5LCB0eXBlID0gInJpZ2h0IikgfiB6LCB4DQogICApJGNoaXNxDQopfSkNCi5wdmFsJGxhYmVsIDwtIHBhc3RlMCgNCiAgInBhc3RlKGl0YWxpYyhwKSwgXCIgPSAiLA0KICBzaWduaWYoMSAtIHBjaGlzcSgucHZhbCRjaGlzcSwgLnB2YWwkZGYpLCAzKSwNCiAgIlwiKSINCikNCi5maXQgPC0gZGF0YS5mcmFtZSh4ID0gLmZpdCR0aW1lLCB5ID0gLmZpdCRzdXJ2LCBucmlzayA9IC5maXQkbi5yaXNrLCANCiAgbmV2ZW50ID0gLmZpdCRuLmV2ZW50LCBuY2Vuc29yPSAuZml0JG4uY2Vuc29yLCB1cHBlciA9IC5maXQkdXBwZXIsIGxvd2VyID0gDQogIC5maXQkbG93ZXIpDQouZGYgPC0gLmRmWyFkdXBsaWNhdGVkKC5kZlssYygieCIsICJ6IildKSwgXQ0KLmRmIDwtIC5maXQgPC0gZGF0YS5mcmFtZSguZml0LCAuZGZbLCBjKCJ6IiksIGRyb3AgPSBGQUxTRV0pDQouZGYgPC0gLmZpdCA8LSByYmluZCh1bmlxdWUoZGF0YS5mcmFtZSh4ID0gMCwgeSA9IDEsIG5yaXNrID0gTkEsIG5ldmVudCA9IA0KICBOQSwgbmNlbnNvciA9IE5BLCB1cHBlciA9IDEsIGxvd2VyID0gMSwgLmRmWywgYygieiIpLCBkcm9wID0gRkFMU0VdKSksIC5maXQpDQouY2VucyA8LSBzdWJzZXQoLmZpdCwgbmNlbnNvciA9PSAxKQ0KLnRtcDEgPC0gZGF0YS5mcmFtZShhcy50YWJsZShieSguZGYsIC5kZlssIGMoInoiKSwgZHJvcCA9IEZBTFNFXSwgDQogIGZ1bmN0aW9uKGQpIG1heChkJG5yaXNrLCBuYS5ybSA9IFRSVUUpKSkpDQoudG1wMSR4IDwtIDANCi5ucmlzayA8LSAudG1wMQ0KZm9yIChpIGluIDE6Mykgey5kZiA8LSBzdWJzZXQoLmZpdCwgeCA8IDcgKiBpKTsgLnRtcDIgPC0gDQogIGRhdGEuZnJhbWUoYXMudGFibGUoYnkoLmRmLCAuZGZbLCBjKCJ6IiksIGRyb3AgPSBGQUxTRV0sIGZ1bmN0aW9uKGQpIGlmIA0KICAoYWxsKGlzLm5hKGQkbnJpc2spKSkgTkEgZWxzZSBtaW4oZCRucmlzayAtIGQkbmV2ZW50IC0gZCRuY2Vuc29yLCBuYS5ybSA9IA0KICBUUlVFKSkpKTsgLnRtcDIkeCA8LSA3ICogaTsgLnRtcDIkRnJlcVtpcy5uYSgudG1wMiRGcmVxKV0gPC0gDQogIC50bXAxJEZyZXFbaXMubmEoLnRtcDIkRnJlcSldOyAudG1wMSA8LSAudG1wMjsgLm5yaXNrIDwtIHJiaW5kKC5ucmlzaywgDQogIC50bXAyKX0NCi5ucmlzayR5IDwtIHJlcChzZXEoMC4xMjUsIDAuMDI1LCAtMC4wNSksIDQpDQoucGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IC5maXQsIGFlcyh4ID0geCwgeSA9IHksIGNvbG91ciA9IHopKSArIA0KICBnZW9tX3N0ZXAoZGF0YSA9IHN1YnNldCguZml0LCAhaXMubmEodXBwZXIpKSwgYWVzKHkgPSB1cHBlciksIHNpemUgPSAxLCANCiAgbHR5ID0gMiwgYWxwaGEgPSAwLjUsIHNob3cubGVnZW5kID0gRkFMU0UsIG5hLnJtID0gRkFMU0UpICsgDQogIGdlb21fc3RlcChkYXRhID0gc3Vic2V0KC5maXQsICFpcy5uYShsb3dlcikpLCBhZXMoeSA9IGxvd2VyKSwgc2l6ZSA9IDEsIA0KICBsdHkgPSAyLCBhbHBoYSA9IDAuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgbmEucm0gPSBGQUxTRSkgKyANCiAgZ2VvbV9zdGVwKHNpemUgPSAxLjUpICsgDQogIGdlb21fbGluZXJhbmdlKGRhdGEgPSAuY2VucywgYWVzKHggPSB4LCB5bWluID0geSwgeW1heCA9IHkgKyAwLjAyKSwgc2l6ZSANCiAgPSAxLjUpICsgDQogIGdlb21fdGV4dChkYXRhID0gLnB2YWwsIGFlcyh5ID0geSwgeCA9IHgsIGxhYmVsID0gbGFiZWwpLCBjb2xvdXIgPSANCiAgImJsYWNrIiwgaGp1c3QgPSAwLCB2anVzdCA9IC0wLjUsIHBhcnNlID0gVFJVRSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgc2l6ZSA9IA0KICAxNCAqIDAuMjgyLCBmYW1pbHkgPSAic2FucyIpICsgDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMjEsIGJ5ID0gNyksIGxpbWl0cyA9IGMoMCwgMjEpKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSwgZXhwYW5kID0gYygwLjAxLCAwKSkgKyANCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArIA0KICB4bGFiKCJUaW1lIGZyb20gZW50cnkiKSArIA0KICB5bGFiKCJQcm9wb3J0aW9uIG9mIHN1cnZpdmFsIikgKyANCiAgbGFicyhjb2xvdXIgPSAiUXRkZV9kZXBlbmRlbnRlcyIpICsgDQogIHRoZW1lX2dyZXkoYmFzZV9zaXplID0gMTQsIGJhc2VfZmFtaWx5ID0gInNhbnMiKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIA0KICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IikpDQoubnJpc2skeSA8LSAoKC5ucmlzayR5IC0gMC4wMjUpIC8gKG1heCgubnJpc2skeSkgLSAwLjAyNSkgKyAwLjEyNSkgKiAwLjgNCi5wbG90MiA8LSBnZ3Bsb3QoZGF0YSA9IC5ucmlzaywgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSBGcmVxLCBjb2xvdXIgPSANCiAgeikpICsgDQogIGdlb21fdGV4dChzaXplID0gMTQgKiAwLjI4MiwgZmFtaWx5ID0gInNhbnMiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDIxLCBieSA9IDcpLCBsaW1pdHMgPSBjKDAsIDIxKSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsgDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKyANCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBzdXJ2aXZhbCIpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlzayh0aGVtZV9ncmV5LCAxNCwgInNhbnMiKQ0KLnBsb3QzIDwtIGdncGxvdChkYXRhID0gc3Vic2V0KC5ucmlzaywgeCA9PSAwKSwgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSB6LA0KICAgY29sb3VyID0geikpICsgDQogIGdlb21fdGV4dChoanVzdCA9IDAsIHNpemUgPSAxNCAqIDAuMjgyLCBmYW1pbHkgPSAic2FucyIpICsgDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LCA1KSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsgDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKyANCiAgUmNtZHJQbHVnaW4uS01nZ3Bsb3QyOjp0aGVtZV9uYXRyaXNrMjEodGhlbWVfZ3JleSwgMTQsICJzYW5zIikNCi5wbG90YiA8LSBnZ3Bsb3QoLmRmLCBhZXMoeCA9IHgsIHkgPSB5KSkgKyANCiAgZ2VvbV9ibGFuaygpICsgDQogIFJjbWRyUGx1Z2luLktNZ2dwbG90Mjo6dGhlbWVfbmF0cmlza2JnKHRoZW1lX2dyZXksIDE0LCAic2FucyIpDQpncmlkOjpncmlkLm5ld3BhZ2UoKTsgZ3JpZDo6cHVzaFZpZXdwb3J0KGdyaWQ6OnZpZXdwb3J0KGxheW91dCA9IA0KICBncmlkOjpncmlkLmxheW91dCgyLCAyLCBoZWlnaHRzID0gdW5pdChjKDEsIDMuNSksIGMoIm51bGwiLCAibGluZXMiKSksIA0KICB3aWR0aHMgID0gdW5pdChjKDQsIDEpLCBjKCJsaW5lcyIsICJudWxsIikpKSkpOyBwcmludCgucGxvdGIsIHZwID0gDQogIGdyaWQ6OnZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMToyLCBsYXlvdXQucG9zLmNvbCA9IDE6MikpOyBwcmludCgucGxvdCAsIA0KICB2cCA9IGdyaWQ6OnZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMSAgLCBsYXlvdXQucG9zLmNvbCA9IDE6MikpOyANCiAgcHJpbnQoLnBsb3QyLCB2cCA9IGdyaWQ6OnZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMiAgLCBsYXlvdXQucG9zLmNvbCA9IA0KICAxOjIpKTsgcHJpbnQoLnBsb3QzLCB2cCA9IGdyaWQ6OnZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMiAgLCANCiAgbGF5b3V0LnBvcy5jb2wgPSAxICApKTsgLnBsb3QgPC0gcmVjb3JkUGxvdCgpDQpwcmludCgucGxvdCkNCnJtKC5kZiwgLmZpdCwgLnB2YWwsIC5wcHZhbCwgLmNlbnMsIC50bXAxLCAudG1wMiwgLm5yaXNrLCAucGxvdCwgLnBsb3QyLCANCiAgLnBsb3QzLCAucGxvdGIpDQpgYGANCg0KYGBge3J9DQouU3VydmZpdCA8LSBzdXJ2Zml0KFN1cnYodGVtcG8sIHN0YXR1cywgdHlwZT0icmlnaHQiKSB+IFF0ZGVfZGVwZW5kZW50ZXMsIA0KICBjb25mLnR5cGU9ImxvZyIsIGNvbmYuaW50PTAuOTUsIHR5cGU9ImthcGxhbi1tZWllciIsIGVycm9yPSJncmVlbndvb2QiLCANCiAgZGF0YT1tZXMwNjE5KQ0KLlN1cnZmaXQNCg0KcXVhbnRpbGUoLlN1cnZmaXQsIHF1YW50aWxlcz1jKC4yNSwuNSwuNzUpKSANCnJlbW92ZSguU3VydmZpdCkNCmBgYA0KDQoNCiMjIFJlZ3Jlc3PDo28gTG9nw61zdGljYQ0KDQpgYGB7cn0NCmluZGljZXMgPC0gc2FtcGxlKDE6bnJvdyhtZXMwNjE5KSxmbG9vcihucm93KG1lczA2MTkpKi44KSkNCnRyZWlubyA8LSBtZXMwNjE5W2luZGljZXMsXQ0KdGVzdGUgPC0gbWVzMDYxOVstaW5kaWNlcyxdDQoNCkdMTS4xIDwtIGdsbShzdGF0dXMgfiBRdGRlX2RlcGVuZGVudGVzICsgU0VYTyArIFRpcG9fUmVnaWFvICsgRGVzY19SZW5kYV9CcnV0YSArIGlkX2luaV9zZXJ2X3B1YiwgDQogICAgICAgICAgICAgZmFtaWx5PWJpbm9taWFsKGxvZ2l0KSwgZGF0YT0gdHJlaW5vKQ0Kc3VtbWFyeShHTE0uMSkNCmV4cChjb2VmKEdMTS4xKSkNCmBgYA0KYGBge3J9DQptb2RmaW5hbCA8LSBzdGVwKEdMTS4xLHNjb3BlID0gbGlzdChsb3dlcj1+MSkpDQpzdW1tYXJ5KG1vZGZpbmFsKQ0KDQpgYGANCg0KYGBge3J9DQp0YWJlbGEgPC0gdGFibGUoR0xNLjEkZml0dGVkLnZhbHVlcz4uNTUsdHJlaW5vJHN0YXR1cykNCnRhYmVsYSAlPiUga2FibGUoKQ0Kc3VtKGRpYWcodGFiZWxhKSkvc3VtKHRhYmVsYSkNCmBgYA0KDQpgYGB7cn0NCnJlc3VsdCA8LSBwcmVkaWN0KG1vZGZpbmFsLHRyZWlubywicmVzcG9uc2UiKQ0KcHJlZCA8LSBwcmVkaWN0aW9uKHJlc3VsdCx0cmVpbm8kc3RhdHVzKQ0KcGVyZiA8LSBwZXJmb3JtYW5jZShwcmVkLCJmcHIiLCJmbnIiKQ0KcGxvdChwZXJmLHByaW50LmN1dG9mZnMuYXQ9c2VxKC4xLC45LGJ5PS4wNSkpDQpgYGANCg0K